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" <[email protected]> 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 <[email protected]>:
>>>> 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
>>>>
>>>>
>>>>
>>
>>