FINERACT-2194: Batch jobs arre failing in a multitenant environment
This commit is contained in:
committed by
Arnold Gálovics
parent
08dc3b123f
commit
c1ec3d7fc7
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.jobs;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
|
||||
public class TenantAwareEqualsHashCodeAdvice implements MethodInterceptor {
|
||||
|
||||
private final Object target;
|
||||
private final String tenantIdentifier;
|
||||
|
||||
public TenantAwareEqualsHashCodeAdvice(Object target) {
|
||||
this.target = target;
|
||||
FineractPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
||||
this.tenantIdentifier = tenant != null ? tenant.getTenantIdentifier() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||
String methodName = method.getName();
|
||||
|
||||
if ("equals".equals(methodName) && args.length == 1) {
|
||||
Object other = args[0];
|
||||
|
||||
if (other instanceof Factory) {
|
||||
|
||||
TenantAwareEqualsHashCodeAdvice otherProxy = (TenantAwareEqualsHashCodeAdvice) ((Factory) other).getCallback(0);
|
||||
return Objects.equals(target, otherProxy.target) && Objects.equals(tenantIdentifier, otherProxy.tenantIdentifier);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("hashCode".equals(methodName) && args.length == 0) {
|
||||
return Objects.hash(target.hashCode(), tenantIdentifier);
|
||||
}
|
||||
|
||||
return proxy.invoke(target, args);
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import org.apache.fineract.infrastructure.jobs.TenantAwareEqualsHashCodeAdvice;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
// Temporary solution until spring-batch fixes the concurrency issue
|
||||
// https://github.com/spring-projects/spring-batch/issues/4774
|
||||
// Mostly copy from spring-batch
|
||||
@SuppressWarnings({ "HideUtilityClassConstructor" })
|
||||
public class JobSynchronizationManager {
|
||||
|
||||
private static final SynchronizationManagerSupport<JobExecution, JobContext> manager = new SynchronizationManagerSupport<>() {
|
||||
|
||||
@Override
|
||||
protected JobContext createNewContext(JobExecution execution) {
|
||||
return new JobContext(execution);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close(JobContext context) {
|
||||
context.close();
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
public static JobContext getContext() {
|
||||
return manager.getContext();
|
||||
}
|
||||
|
||||
public static JobContext register(JobExecution jobExecution) {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(JobExecution.class);
|
||||
enhancer.setCallback(new TenantAwareEqualsHashCodeAdvice(jobExecution));
|
||||
return manager.register((JobExecution) enhancer.create(new Class[] { JobInstance.class, Long.class, JobParameters.class },
|
||||
new Object[] { jobExecution.getJobInstance(), jobExecution.getId(), jobExecution.getJobParameters() }));
|
||||
}
|
||||
|
||||
public static void close() {
|
||||
manager.close();
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
manager.release();
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.springframework.batch.core.scope.context;
|
||||
|
||||
import org.apache.fineract.infrastructure.jobs.TenantAwareEqualsHashCodeAdvice;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
// Temporary solution until spring-batch fixes the concurrency issue
|
||||
// https://github.com/spring-projects/spring-batch/issues/4774
|
||||
// Mostly copy from spring-batch
|
||||
@SuppressWarnings({ "HideUtilityClassConstructor" })
|
||||
public class StepSynchronizationManager {
|
||||
|
||||
private static final SynchronizationManagerSupport<StepExecution, StepContext> manager = new SynchronizationManagerSupport<>() {
|
||||
|
||||
@Override
|
||||
protected StepContext createNewContext(StepExecution execution) {
|
||||
return new StepContext(execution);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close(StepContext context) {
|
||||
context.close();
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
public static StepContext getContext() {
|
||||
return manager.getContext();
|
||||
}
|
||||
|
||||
public static StepContext register(StepExecution stepExecution) {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(StepExecution.class);
|
||||
enhancer.setCallback(new TenantAwareEqualsHashCodeAdvice(stepExecution));
|
||||
return manager.register((StepExecution) enhancer.create(new Class[] { String.class, JobExecution.class },
|
||||
new Object[] { stepExecution.getStepName(), stepExecution.getJobExecution() }));
|
||||
}
|
||||
|
||||
public static void close() {
|
||||
manager.close();
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
manager.release();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user