Я попытаюсь резюмировать свою проблему
У меня есть служба REST, которая выполняет процесс 4 раза. Каждая итерация не зависит от предыдущей, поэтому я хочу выполнить эти 4 итерации параллельно.
Я использую Java в Quarkus с MicroProfile и Hibernate OMR (и другими вещами, такими как Lombok)
Проблема: Я думаю, что достиг своей цели, но 1/3 раза я вызываю службу REST, она терпит неудачу, но остальные 2/3 работают нормально.
Когда он терпит неудачу, я получаю это исключение :
2020-08-05 13:06:37,353 WARN [com.arj.ats.arjuna] (executor-thread-2) ARJUNA012127: TwoPhaseCoordinator.afterCompletion - returned failure for SynchronizationImple< 0:ffffc0a832eb:efa4:5f2a92b3:53, io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager$1@549ed75a >
2020-08-05 13:06:37,353 WARN [org.hib.res.tra.bac.jta.int.syn.SynchronizationCallbackCoordinatorTrackingImpl] (executor-thread-2) HHH000451: Transaction afterCompletion called by a background thread; delaying afterCompletion processing until the original thread can handle it. [status=4]
2020-08-05 13:06:37,354 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-2) HTTP Request to /arbol/v1/estructura/generar-estructura failed, error id: 58aaf095-1659-4050-8ef9-92aeffa5164b-4: org.jboss.resteasy.spi.UnhandledException: java.util.concurrent.CompletionException: java.lang.NullPointerException
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:216)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:515)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:259)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:160)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:163)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:245)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:132)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:37)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:94)
at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:231)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2046)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1578)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at java.base/java.lang.Thread.run(Thread.java:832)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.util.concurrent.CompletionException: java.lang.NullPointerException
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1766)
at io.smallrye.context.SmallRyeThreadContext$ContextualRunnable.run(SmallRyeThreadContext.java:56)
... 11 more
Caused by: java.lang.NullPointerException
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:81)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1325)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1405)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1565)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533)
at org.hibernate.query.Query.getResultList(Query.java:165)
at es.metadata.repository.UtRepository.obtenerUts(UtRepository.java:46)
at es.metadata.repository.UtRepository_Subclass.obtenerUts$$superaccessor3(UtRepository_Subclass.zig:844)
at es.metadata.repository.UtRepository_Subclass$$function$$3.apply(UtRepository_Subclass$$function$$3.zig:33)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInCallerTx(TransactionalInterceptorBase.java:244)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorSupports.doIntercept(TransactionalInterceptorSupports.java:34)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:53)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorSupports.intercept(TransactionalInterceptorSupports.java:26)
at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorSupports_Bean.intercept(TransactionalInterceptorSupports_Bean.zig:339)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at es.metadata.repository.UtRepository_Subclass.obtenerUts(UtRepository_Subclass.zig:801)
at es.metadata.repository.UtRepository_ClientProxy.obtenerUts(UtRepository_ClientProxy.zig:398)
at es.metadata.service.UtService.obtenerTodas(UtService.java:23)
at es.metadata.service.UtService_ClientProxy.obtenerTodas(UtService_ClientProxy.zig:315)
at es.metadata.service.EstructuraArbolService.generarEstructuraEmpresaUnica(EstructuraArbolService.java:120)
at es.metadata.service.EstructuraArbolService_Subclass.generarEstructuraEmpresaUnica$$superaccessor14(EstructuraArbolService_Subclass.zig:2836)
at es.metadata.service.EstructuraArbolService_Subclass$$function$$14.apply(EstructuraArbolService_Subclass$$function$$14.zig:47)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:54)
at io.quarkus.arc.impl.ActivateRequestContextInterceptor.aroundInvoke(ActivateRequestContextInterceptor.java:20)
at io.quarkus.arc.impl.ActivateRequestContextInterceptor_Bean.intercept(ActivateRequestContextInterceptor_Bean.zig:275)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:41)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:41)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:32)
at es.metadata.service.EstructuraArbolService_Subclass.generarEstructuraEmpresaUnica(EstructuraArbolService_Subclass.zig:2789)
at es.metadata.service.EstructuraArbolService.lambda$0(EstructuraArbolService.java:73)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1764)
... 12 more
Что у меня есть: Я очень потерялся с этим исключением. Я даже не знаю, в каком слое проблема. Я не знаю, что это означает, либо исключение NullPointerException, потому что иногда работает. Для меня это не имеет смысла
Затем я публикую части своего кода, чтобы показать, что у меня есть.
Репозитории: Все XRepository эквивалентны (UtRepository, UgUtRepository ...)
@Transactional(SUPPORTS)
public abstract class AbstractRepository<E, P> {
private final Class<E> entityClass;
public AbstractRepository(Class<E> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
// some queries
}
@ApplicationScoped
public class UgRepository extends AbstractRepository<Ug, Integer> {
@Inject
@PackagePrivate
EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public UgRepository() {
super(Ug.class);
}
public List<Ug> obtenerUgs(Integer idEmpresa) {
Query query = em.createNamedQuery("Ug.obtenerTodos");
query.setParameter("idEmpresa", idEmpresa);
return ListCaster.castearLista(Ug.class, query.getResultList());
}
// some queries
}
Сущности: Все сущности являются эквивалентами (Ut, UgUt ...)
@Entity
@Table(name = "ug")
@NamedQueries({
@NamedQuery(name = "Ug.obtenerTodos", query = "SELECT ug FROM Ug ug WHERE ug.empresaPrincipal.idEmpresa = :idEmpresa")
// some queries})
@Getter
@Setter
public class Ug {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_ug", table = "ug", nullable = false)
private Integer idUg;
// some columns and relationships
public Ug() {
}
}
сервис, который выполняет 4 вызова алгоритма: (generarEstructuraEmpresaUnica)
Внутри метода «generarEstructuraEmpresaUnica» я делаю несколько SELECT для BD, и у меня есть рекурсивный метод. Я думаю, что проблема может быть здесь (в запросах к BD), потому что в трассировке исключений вы можете увидеть "UtRepository"
Кроме того, репозиторий, показанный в исключении, всегда будет другим. Иногда это "UgRepository", иногда "UtRepository", "UgUtRepository" ...
@Inject
ManagedExecutor executor;
@Transactional
public JSONObject generarEstructuraEmpresas(List<EmpresaPrincipal> lista)
throws InterruptedException, ExecutionException {
JSONObject arbol = new JSONObject();
List<CompletableFuture<JSONObject>> listaArboles = new ArrayList<>();
for (int i = 0; i < lista.size(); i++) {
final Integer posLista = i;
CompletableFuture<JSONObject> future = CompletableFuture
.supplyAsync(() -> generarEstructuraEmpresaUnica(lista.get(posLista), posLista + 1,
lista.size() == 1 ? Boolean.TRUE : Boolean.FALSE), executor);
listaArboles.add(future);
}
CompletableFuture<Void> completationList = CompletableFuture
.allOf(listaArboles.toArray(CompletableFuture[]::new));
CompletableFuture<List<JSONObject>> completationListJSON = completationList
.thenApply(avoid -> listaArboles.stream().map(CompletableFuture::join).collect(Collectors.toList()));
arbol.put("Arbol", completationListJSON.join());
return arbol;
}
Если вам нужна дополнительная информация, сообщите мне. Не хочу задавать огромный вопрос