tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Romain Manni-Bucau <rmannibu...@gmail.com>
Subject Re: "Unit" testing with OpenEJB / TomEE and JSF, need FacesContext
Date Tue, 03 Feb 2015 21:09:36 GMT
well

in embedded mode the javaagent on the JVM (and no other solution)
should be fine. That said I saw surprises on java 8 even with this and
sometimes you can just enhance at build time - was not on eclipselinks
so maybe this doesnt apply.

What can happen is you dont reuse javaagent classes cause eclipselink
is in a lower classloader, maybe try to force the classloader to skip
eclipselink classes when using the javaagent


Romain Manni-Bucau
@rmannibucau
http://www.tomitribe.com
http://rmannibucau.wordpress.com
https://github.com/rmannibucau


2015-02-03 21:01 GMT+01:00 Randy Tidd <randy_fi@tidd.cc>:
> Romain,
>
> Thanks again for the help. However one more follow-up question...
>
> I am using EclipseLink.  As I'm sure you know (but for the benefit of other readers),
EclipseLink needs either dynamic or static "weaving" of entity classes to be supported in
order to provide lazy loading of some relationships.  We deploy to Glassfish which evidently
supports dynamic weaving automatically and we rely on lazy loading for good performance. 
I want to replicate this behavior as closely as possible in my unit tests, which use embedded
TomEE.
>
> How can I configure embedded TomEE / OpenEJB to provide dynamic weaving?  I tried adding
the eclipselink jar as the javaagent in the unit test configuration and then adding these
properties:
>
>                 props.put("eclipselink.weaving", "dynamic");
>                 props.put("eclipselink.weaving.lazy", "true");
>                 props.put("eclipselink.weaving.internal", "true");
>
>                 container = EJBContainer.createEJBContainer(props);
>
> When I run it I can see in the log messages that it is using weaving:
>
> [EL Finest]: ServerSession(66487094)--Thread(Thread[main,5,main])--property=eclipselink.weaving.changetracking;
default value=true
> [EL Finest]: ServerSession(66487094)--Thread(Thread[main,5,main])--property=eclipselink.weaving.lazy;
value=true
> [EL Finest]: ServerSession(66487094)--Thread(Thread[main,5,main])--property=eclipselink.weaving.eager;
default value=false
> [EL Finest]: ServerSession(66487094)--Thread(Thread[main,5,main])--property=eclipselink.weaving.fetchgroups;
default value=true
> [EL Finest]: ServerSession(66487094)--Thread(Thread[main,5,main])--property=eclipselink.weaving.internal;
value=true
>
> and
>
> [EL Finer]: ServerSession(66487094)--Thread(Thread[main,5,main])--Class [com.xxx.RequestForClassPublic]
registered to be processed by weaver.
>
> But on the first query, I get this error:
>
> SEVERE: EjbTransactionUtil.handleSystemException: com.xxx.AbstractModifiableEntity.<init>(Lorg/eclipse/persistence/internal/descriptors/PersistenceObject;)V
> java.lang.NoSuchMethodError: com.xxx.AbstractModifiableEntity.<init>(Lorg/eclipse/persistence/internal/descriptors/PersistenceObject;)V
>         at com.xxx.RequestForClassPublic.<init>(RequestForClassPublic.java)
>         at com.xxx.RequestForClassPublic._persistence_new(RequestForClassPublic.java)
>         at org.eclipse.persistence.internal.descriptors.PersistenceObjectInstantiationPolicy.buildNewInstance(PersistenceObjectInstantiationPolicy.java:30)
>         at org.eclipse.persistence.descriptors.ClassDescriptor.selfValidationAfterInitialization(ClassDescriptor.java:3870)
>         at org.eclipse.persistence.descriptors.ClassDescriptor.validateAfterInitialization(ClassDescriptor.java:5688)
>         at org.eclipse.persistence.descriptors.ClassDescriptor.postInitialize(ClassDescriptor.java:3547)
>         at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:526)
>         at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:476)
>         at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:435)
>         at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:676)
>         at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:634)
>         at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:284)
>         at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:294)
>         at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:279)
>         at org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory.createEntityManager(ReloadableEntityManagerFactory.java:162)
>         at org.apache.openejb.persistence.JtaEntityManagerRegistry.getEntityManager(JtaEntityManagerRegistry.java:119)
>         at org.apache.openejb.persistence.JtaEntityManager.getEntityManager(JtaEntityManager.java:96)
>         at org.apache.openejb.persistence.JtaEntityManager.proxyIfNoTx(JtaEntityManager.java:326)
>         at org.apache.openejb.persistence.JtaEntityManager.createQuery(JtaEntityManager.java:280)
>
> Our entity classes such as RequestForClassPublic inherit from an abstract superclass
AbstractModifiableEntity. It seems that EclipseLink can't find the default constructor, which
is there in both classes, and works when weaving is not enabled.
>
> I realize that this might be more of an EclipseLink question than a TomEE question but
I'd appreciate any info.
>
> Thanks,
> Randy
>
> On Jan 28, 2015, at 6:41 PM, Romain Manni-Bucau wrote:
>
>> Both would work.
>>
>> arquillian-tomee-remote or arquillian-tomee-embedded artifact are our
>> arquillian integrations.
>>
>> Without you need some custome code glue, not sure it is the best to go
>> while tomee 2 is not released.
>> Le 29 janv. 2015 00:32, "Randy Tidd" <randy_fi@tidd.cc> a écrit :
>>
>>> Romain,
>>>
>>> Thank you for your reply this was helpful.  Switching from "openejb-core"
>>> to "tomee-embedded" has fixed the problem of the missing javaee
>>> implementations, I am now able to mock the FacesContext and other JSF
>>> resources for the unit tests, and the glassfish-embeded package was not
>>> needed.
>>>
>>> I wonder if I can ask a follow up question. I would like to inject my JSF
>>> beans and EJB's into my unit test class, so they will all be managed by
>>> TomEE.  Trying this:
>>>
>>> @ManagedBean
>>> @ViewScoped
>>> public abstract class FooBean ...
>>>
>>> ...
>>>
>>> @Inject
>>> FooBean fooBean;
>>>
>>> I get:
>>>
>>> Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Api
>>> type [...FooBean] is not found with the qualifiers
>>> Qualifiers: [@javax.enterprise.inject.Default()]
>>>
>>> I see toolkits like Arquillian which are intended to support this, I am
>>> looking for information on if or how this works with TomEE or if TomEE can
>>> handle this without Arquillian, again any info appreciated.
>>>
>>> Randy
>>>
>>> On Jan 28, 2015, at 10:24 AM, Romain Manni-Bucau wrote:
>>>
>>>> Hi
>>>>
>>>> Several points (without any order)
>>>> 1) javax:javaee-api:6.0 is broken don't use it for any run
>>>> (org.apache.openejb:javaee-api + myfaces-api can replace it)
>>>> 2) before InvalidApplicationException the error is logged and that's
>>>> what will help you to solve the issue, this exception is just here to
>>>> make the deployment failing
>>>> 3) openejb 2 will be able to run jsf in embedded mode (we use it for cdi
>>> tck)
>>>> 4) tomee 1.x can already do it using tomee-embedded instead of openejb
>>>> 5) don't know that much your solution but maybe you just miss
>>>> myfaces-api, myfaces-impl, tomcat-jasper, tomcat-jasper-el,
>>>> openejb-jstl dependencies. (check here adapting your versions
>>>>
>>> https://git-wip-us.apache.org/repos/asf?p=tomee.git;a=blob;f=tck/cdi-embedded/pom.xml;h=d33af5dc0cef62b93f3e46a41d4c776befd50ed8;hb=21ad55b9f9e07c638ab53a6abc5451c680c29ba7
>>> )
>>>>
>>>> Hope it gives you few pointers
>>>>
>>>>
>>>> Romain Manni-Bucau
>>>> @rmannibucau
>>>> http://www.tomitribe.com
>>>> http://rmannibucau.wordpress.com
>>>> https://github.com/rmannibucau
>>>>
>>>>
>>>> 2015-01-28 16:17 GMT+01:00 Randy Tidd <randy_fi@tidd.cc>:
>>>>> I set up some "unit" tests (really integration tests) using embedded
>>> OpenEJB with this:
>>>>>
>>>>>   <dependency>
>>>>>       <groupId>org.apache.openejb</groupId>
>>>>>       <artifactId>openejb-core</artifactId>
>>>>>       <version>4.7.1</version>
>>>>>       <scope>test</scope>
>>>>>   </dependency>
>>>>>
>>>>> I am able to call my EJB methods which use JPA and this works great.
>>>>>
>>>>> My app is J2EE deployed to Glassfish and I would like to expand the
>>> unit testing to the JSF managed bean classes.  I am able to invoke methods
>>> on those beans with the same setup.  However, those beans reference
>>> FacesContext with calls like this:
>>>>>
>>>>>       Principal principal =
>>> FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
>>>>>
>>>>> This blows up with an exception because FacesContext is not available
>>> in embedded OpenEJB.
>>>>>
>>>>> The FacesContext can be mocked with something like Mockito, but this
>>> code does not run without a javaee implementation on the classpath, as
>>> described here:
>>>>>
>>>>>
>>> https://developer.jboss.org/wiki/WhatsTheCauseOfThisExceptionJavalangClassFormatErrorAbsentCode
>>>>>
>>>>> Essentially, including a Maven dependency like this:
>>>>>
>>>>>       <dependency>
>>>>>           <groupId>javax</groupId>
>>>>>           <artifactId>javaee-api</artifactId>
>>>>>           <version>6.0</version>
>>>>>           <scope>provided</scope>
>>>>>       </dependency>
>>>>>
>>>>> Provides only the API's for the javaee classes which allows the code
to
>>> compile, but does not provide an implementation, so it can't run.  When the
>>> code runs inside a container like Glassfish, the implementation is there.
>>> But when running as a unit test, there is no such implementation unless it
>>> is explicitly added.
>>>>>
>>>>> I tried adding this:
>>>>>
>>>>>           <dependency>
>>>>>               <groupId>org.glassfish.main.extras</groupId>
>>>>>               <artifactId>glassfish-embedded-all</artifactId>
>>>>>               <version>3.1.2.2</version>
>>>>>               <scope>test</scope>
>>>>>           </dependency>
>>>>>
>>>>> My understanding is that this is supposed to provide Glassfish classes
>>> at runtime with test scope which is intended to address this problem.
>>> However, when I run this with OpenEJB, I get this:
>>>>>
>>>>> org.apache.openejb.OpenEjbContainer$InvalidApplicationException:
>>> org.apache.openejb.config.ValidationFailedException: Module failed
>>> validation. AppModule(name=)
>>>>>       at
>>> org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:320)
>>>>>       at
>>> javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:56)
>>>>>       at
>>> com.aoi.aoiweb.ejb.RegistrarEjbTest.initialize(RegistrarEjbTest.java:71)
>>>>>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>>>       at
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>>>       at
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>>>       at java.lang.reflect.Method.invoke(Method.java:597)
>>>>>       at
>>> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
>>>>>       at
>>> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
>>>>>       at
>>> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
>>>>>       at
>>> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
>>>>>       at
>>> org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
>>>>>       at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
>>>>>       at
>>> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
>>>>>       at
>>> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
>>>>>       at
>>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
>>>>>       at
>>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
>>>>>       at
>>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
>>>>>       at
>>> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
>>>>> Caused by: org.apache.openejb.config.ValidationFailedException: Module
>>> failed validation. AppModule(name=)
>>>>>       at
>>> org.apache.openejb.config.ReportValidationResults.deploy(ReportValidationResults.java:88)
>>>>>       at
>>> org.apache.openejb.config.AppInfoBuilder.build(AppInfoBuilder.java:309)
>>>>>       at
>>> org.apache.openejb.config.ConfigurationFactory.configureApplication(ConfigurationFactory.java:965)
>>>>>       at
>>> org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:314)
>>>>>       ... 18 more
>>>>>
>>>>> I suspect that the glassfish-embedded-all dependency is conflicting
>>> with OpenEJB since they both attempt to provide the same classes and would
>>> each be configured differently.
>>>>>
>>>>> So what I think I'm looking for is an "embedded TomEE" or a way to add
>>> javaee implementation classes, or minimally FacesContext, to an embedded
>>> OpenEJB.  I have been searching around the docs and web sites and have not
>>> found much to help, thanks in advance for any info.
>>>>>
>>>>> Randy
>>>>>
>>>>>
>>>>>
>>>
>>>
>

Mime
View raw message