[ 
https://issues.apache.org/jira/browse/TOMEE-4293?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Nicolas Ternisien updated TOMEE-4293:
-------------------------------------
    Attachment: collapsedear-bug-project.tar.gz

> WAR-wide EJB local refs inserted into each EJB at startup
> ---------------------------------------------------------
>
>                 Key: TOMEE-4293
>                 URL: https://issues.apache.org/jira/browse/TOMEE-4293
>             Project: TomEE
>          Issue Type: Bug
>          Components: TomEE Core Server
>    Affects Versions: 8.0.16
>            Reporter: Nicolas Ternisien
>            Priority: Major
>         Attachments: collapsedear-bug-ear.catalina.out, 
> collapsedear-bug-ear.ear, collapsedear-bug-project.tar.gz, 
> collapsedear-bug.war, collapsedear-bug.war.catalina.out
>
>
> We're currently experimenting the migration of an EAR project from Weblogic 
> application server to TomEE.
> While conduction this experiment, we also tried to see if we could rely on 
> "Collapsed EAR" approach, ie, simplifying the application by providing a 
> single WAR file with EJBs embedded into it, instead of multiple ejb and web 
> modules inside the EAR file.
> The project is quite big with:
>  * 1992 EJBs in EJB Module (+ CDI beans)
>  * 1193 EJBs in Web Module (+ CDI beans for JAX RS resources)
>  * (and a total of 8569 injection points via @EJB)
> But still, with the EAR approach, total loading time is about 1min, with 3.1 
> GB JVM memory usage.
>  
> When trying the alternative approach via a WAR file (including the EJB module 
> as JAR), the startup takes huge time (30 to 40 minutes) and JVM memory 
> consumption goes up to 8 GB.
>  
> We tried to investigate this difference and we have identified the bottleneck 
> (via TomEE startup debugging) at JndiEncInfoBuilder, more especially at 
> JndiEncInfoBuilder.buildEjbRefs() where each EJB has the *whole* list of 
> ejbLocalRef of all the EJBs of the entire application.
>  
> I've setup a dedicated project (in attachment), with 2 different deployable 
> binaries:
>  * collapsedear-bug.war
>  * collapsedear-bug-ear.ear
> Note the deployment is performed via the "tomee/apps" folder.
>  
> Both contains an EJB module, named "collapsedear-bug-ejb", which contains the 
> following EJB NumberService.java:
> {code:java}
> package org.lastnico.collapsedear.bug.ejb;
> import java.util.Random;
> import javax.annotation.PostConstruct;
> import javax.ejb.EJB;
> import javax.ejb.Singleton;
> import javax.ejb.Startup;
> import org.slf4j.Logger;
> import org.slf4j.LoggerFactory;
> @Singleton
> @Startup
> public class NumberService {
>     private static Logger log = LoggerFactory.getLogger(NumberFinder.class);
>     @PostConstruct
>     public void start() {
>         log.info("Starting {}", this.getClass());
>     }
>     @EJB
>     private NumberFinder userFinder;
>     public long save() {
>         return new Random().nextLong();
>     }
> }
>  {code}
>  
> To compare the two processes at loading time. Of course, this project is much 
> more simple (less than 10 EJBs in total), so we cannot notice it from memory 
> consumption or loading time, but here are the debugging output:
>  
> h4. collapsedear-bug.war
> At startup, with a debugging breakpoint, watching for "NumberService" EJB 
> registration
> at
> JndiEncInfoBuilder.build(final JndiConsumer jndiConsumer, final String 
> ejbName, final String moduleId, final URI moduleUri, final JndiEncInfo 
> moduleJndiEnc, final JndiEncInfo compJndiEnc) throws OpenEJBException {
> {code:java}
>  moduleId = collapsedear-bug-ejb
> JndiConsumer.ejbClass = "org.lastnico.collapsedear.bug.ejb.NumberService"
> JndiConsumer.ejbLocalRef = 
> {java:comp/env/org.lastnico.collapsedear.bug.ejb.NumberService/userFinder=EjbLocalRef{name='java:comp/env/org.lastnico.collapsedear.bug.ejb.NumberService/userFinder',
>  local=org.lastnico.collapsedear.bug.ejb.NumberFinder, link='null', 
> mappedName='null', lookupName='null'}, 
> java:comp/env/org.lastnico.collapsedear.bug.war.GreetingResource/numberFinder=EjbLocalRef{name='java:comp/env/org.lastnico.collapsedear.bug.war.GreetingResource/numberFinder',
>  local=org.lastnico.collapsedear.bug.ejb.NumberFinder, link='null', 
> mappedName='null', lookupName='null'}, 
> java:comp/env/org.lastnico.collapsedear.bug.war.GreetingResource/calculatorFront=EjbLocalRef{name='java:comp/env/org.lastnico.collapsedear.bug.war.GreetingResource/calculatorFront',
>  local=org.lastnico.collapsedear.bug.war.CalculatorFront, link='null', 
> mappedName='null', lookupName='null'}, 
> java:comp/env/org.lastnico.collapsedear.bug.war.CalculatorFront/numberFinder=EjbLocalRef{name='java:comp/env/org.lastnico.collapsedear.bug.war.CalculatorFront/numberFinder',
>  local=org.lastnico.collapsedear.bug.ejb.NumberFinder, link='null', 
> mappedName='null', lookupName='null'}}{code}
>  
> You can see that ejbLocalRef contains 8 different injection points, while 
> NumberService has only a single injection point (NumberFinder)
> h4. collapsedear-bug-ear.ear
> At the opposite, when  debugging the startup of the equivalent EAR file
> Here are the debugging info extracted:
> {code}
> moduleId = collapsedear-bug-ejb
> JndiConsumer.ejbClass = "org.lastnico.collapsedear.bug.ejb.NumberService"
> JndiConsumer.ejbLocalRef = 
> {java:comp/env/org.lastnico.collapsedear.bug.ejb.NumberService/userFinder=EjbLocalRef{name='java:comp/env/org.lastnico.collapsedear.bug.ejb.NumberService/userFinder',
>  local=org.lastnico.collapsedear.bug.ejb.NumberFinder, link='null', 
> mappedName='null', lookupName='null'}}
> {code}
> This time, as expected, the NumberService EJB only has 1 single EJB local 
> ref, matching its single injection point.
> h4. Suspicion
> I suspect the reason for this is that MergeWebappJndiContext indistinctely 
> copies all possible EJB local refs, and hence each EJB receives the whole 
> list of injection points.
> In the scenario of our application described earlier, we end up with (1992 +  
> 1193) * 8569 declared EJB local refs, which slows down the whole startup and 
> waste huge quantity of memory.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to