0

I have a JSF / JPA / MySQL / EclipseLink GlassFish or Payara application.

A schedule is running inside a stateless EJB. The data is extracted through JPQL using EJBs inside the stateless bean.

When the database queries a small amount of data, the application runs without any issue. When a large number of data is handled, it gives errors. The place that error occurs varies from time to time. There is NO error in the code segments where the error is pointed as the same code runs without any issue in a small amount of data is retrieved. Copying and pasting the same code to a JSF managed bean, runs correctly with a large amount of data. (It can not be used in production as the querying is supposed to be running in a schedule.)

What is the reason for this issue? Is there MySQL / GlassFish settings that can be optimized to prevent this error?

Example of an Error

Warning:   A system exception occurred during an invocation on EJB IndividualQueryResultFacade, method: public void lk.gov.health.phsp.facade.AbstractFacade.edit(java.lang.Object)
Warning:   javax.ejb.TransactionRolledbackLocalException: Client's transaction aborted
at com.sun.ejb.containers.EJBContainerTransactionManager.useClientTx(EJBContainerTransactionManager.java:361)
at com.sun.ejb.containers.EJBContainerTransactionManager.preInvokeTx(EJBContainerTransactionManager.java:255)
at com.sun.ejb.containers.BaseContainer.preInvokeTx(BaseContainer.java:4558)
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:2020)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:210)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy412.edit(Unknown Source)
at lk.gov.health.phsp.facade.__EJB31_Generated__IndividualQueryResultFacade__Intf____Bean__.edit(Unknown Source)
at lk.gov.health.phsp.ejbs.ReportTimerSessionBean.calculateIndividualQueryResult(ReportTimerSessionBean.java:692)
at lk.gov.health.phsp.ejbs.ReportTimerSessionBean.runIndividualQuerys(ReportTimerSessionBean.java:151)
at sun.reflect.GeneratedMethodAccessor174.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4820)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:824)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at org.jboss.weld.module.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:81)
at org.jboss.weld.module.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:823)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundTimeout(SystemInterceptorProxy.java:145)
at sun.reflect.GeneratedMethodAccessor99.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:823)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4792)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4780)
at com.sun.ejb.containers.BaseContainer.callEJBTimeout(BaseContainer.java:4085)
at com.sun.ejb.containers.EJBTimerService.deliverTimeout(EJBTimerService.java:1200)
at com.sun.ejb.containers.EJBTimerService.access$000(EJBTimerService.java:89)
at com.sun.ejb.containers.EJBTimerService$TaskExpiredWork.run(EJBTimerService.java:1919)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

Stateless Bean - Only a small segment is displayed below.

@Stateless public class ReportTimerSessionBean {

private boolean processingReport = false;

@EJB
private StoredQueryResultFacade storeQueryResultFacade;
@EJB
private UploadFacade uploadFacade;
@EJB
private EncounterFacade encounterFacade;
@EJB
private QueryComponentFacade queryComponentFacade;
@EJB
private ClientEncounterComponentItemFacade clientEncounterComponentItemFacade;
@EJB
private ConsolidatedQueryResultFacade consolidatedQueryResultFacade;
@EJB
private IndividualQueryResultFacade individualQueryResultFacade;

private List<QueryComponent> queryComponents;

@Schedule(
        hour = "*",
        minute = "*",
        second = "1",
        persistent = false)
@TransactionAttribute(REQUIRES_NEW)
public void runReports() {
    queryComponents = null;
    if (!processingReport) {
        submitToConsilidate();
    }
    if (!processingReport) {
        checkCompletenessAfterConsolidation();
    }
    if (!processingReport) {
        generateFileAfterConsolidation();
    }

}

@Schedule(
        hour = "*",
        minute = "*",
        second = "16",
        persistent = false)
@TransactionAttribute(REQUIRES_NEW)
public void runIndividualQuerys() {
    System.out.println("Going to run individual queries at " + currentTimeAsString() + ".");
    int singleProcessCount = 5000;
    List<IndividualQueryResult> cqrs;
    String j;
    j = "select r "
            + " from IndividualQueryResult r "
            + " where r.included is null "
            + " order by r.id "
            + " ";
    cqrs = getIndividualQueryResultFacade().findByJpql(j, singleProcessCount);

    if (cqrs == null) {
        System.out.println("No individual queries left to process.");
        return;
    }

    System.out.println("Number of individual queries processing this time is " + cqrs.size());
    for (IndividualQueryResult r : cqrs) {
        calculateIndividualQueryResult(r);
    }

}

@Schedule(
        hour = "*",
        minute = "*",
        second = "31",
        persistent = false)
@TransactionAttribute(REQUIRES_NEW)
public void createIndividualResultsForConsolidatedResults() {
    System.out.println("Going to create individual queries at " + currentTimeAsString());
    int singleProcessCount = 50;
    List<ConsolidatedQueryResult> cqrs;
    String j;
    j = "select r "
            + " from ConsolidatedQueryResult r "
            + " where r.longValue is null "
            + " order by r.id "
            + " ";
    cqrs = getConsolidatedQueryResultFacade().findByJpql(j, singleProcessCount);

    if (cqrs == null) {
        System.out.println("No consolidated queries to create individual queries.");
        return;
    }
    for (ConsolidatedQueryResult r : cqrs) {
        Long lastIndividualQueryResultId = 0l;
        List<Long> encIds = findEncounterIds(r.getResultFrom(), r.getResultTo(), r.getInstitution());
        if (encIds == null) {
            r.setLongValue(0l);
            getConsolidatedQueryResultFacade().edit(r);
            continue;
        }
        if (encIds.isEmpty()) {
            r.setLongValue(0l);
            getConsolidatedQueryResultFacade().edit(r);
            continue;
        }
        for (Long encId : encIds) {
            Long generatedId = createIndividualQueryResultsForConsolidateQueryResult(encId, 
r.getQueryComponentCode());
            if (generatedId > lastIndividualQueryResultId) {
                lastIndividualQueryResultId = generatedId;
            }
        }
        r.setLastIndividualQueryResultId(lastIndividualQueryResultId);
        getConsolidatedQueryResultFacade().edit(r);
    }

}
Buddhika Ariyaratne
  • 2,339
  • 6
  • 51
  • 88
  • 1
    What you've given is too generic - the wrapper thrown when a JTA transaction is forced to handle an exception. You need to get the underlying exception causing the rollback - turn logging up a level or two and check them for exceptions related to this code. – Chris Aug 10 '20 at 15:23
  • I decreased the entities retrieved from a single query from 10,000 to 1,000 and increased the frequency of schedule. That prevented the error. – Buddhika Ariyaratne Aug 10 '20 at 21:52
  • 1
    And the error was? OOM, timeout? There are many ways to solve it if you know the underlying cause. – Chris Aug 11 '20 at 15:42
  • There was no error. I just limit the number of queries processes for a schedule. Initially, I run 1000 queries and later reduced to 50. No change other than that. Now working without error, but have to wait longer to get complete the process. – Buddhika Ariyaratne Aug 12 '20 at 10:06
  • 1
    You run 1000 queries(?) and get an error - what is that error? That underlying error would be the issue, isn't it. If you are running 1000 queries in the same transactional scope, you must not have parameters tuned to handle it. – Chris Aug 12 '20 at 15:14

1 Answers1

1

You use @EJB for a stateless bean. Instead, try to define an Entity Manager side this stateless bean and make all data transactions within. Entity Managers are not threaded safe.

Sunila SS
  • 93
  • 5