override annotation based configuration with ejb-jar.xml

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

override annotation based configuration with ejb-jar.xml

kubamarchwicki
Hi,
Here is my issue with OpenEJB. I'm note sure if what I'm trying to do is not possible or I'm doing something wrong.

I use OpenEJB only for testing - embedded container. In the application I have multiple beans implementing same business interface, one main - with logic, few other in tests. What I'm looking for is possibility to (after bootstrapping container) override wired dependencies with the testing implementation.
How I understand OpenEJB lifecycle, first ejb-jar.xml is evaluated. After that - class path discovery is performed. In either cases it doesn't work for me. When I put something like this in ejb-jar.xml a NullPointer is thrown (MethodController is my business service, AnotherTestingDisplayingService is a testing mockup)
        <session>
            <ejb-name>MethodController</ejb-name>
            <ejb-ref>
                <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
                <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
                <ejb-link>AnotherTestingDisplayingService</ejb-link>
                <injection-target>
                    <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
                    <injection-target-name>displayingService</injection-target-name>
                </injection-target>
            </ejb-ref>

Sounds reasonable, MethodController is not yet present in context.

On the other hand, when I fully define MethodController in ejb-jar.xml (like this)
<session id="MethodController">
            <ejb-name>MethodController</ejb-name>
            <mapped-name></mapped-name>
            <business-local>pl.marchwicki.ejb.controllers.MethodControllerLocal</business-local>
            <ejb-class>pl.marchwicki.ejb.controllers.MethodController</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
            <ejb-ref>
                <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
                <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
                <ejb-link>AnotherTestingDisplayingService</ejb-link>
                <injection-target>
                    <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
                    <injection-target-name>displayingService</injection-target-name>
                </injection-target>
            </ejb-ref>
            <ejb-ref>
                <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/calculatingService</ejb-ref-name>
                <remote>pl.marchwicki.ejb.business.CalculatingServiceLocal</remote>
                <injection-target>
                    <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
                    <injection-target-name>calculatingService</injection-target-name>
                </injection-target>
            </ejb-ref>
        </session> 

I get javax.naming.NameAlreadyBoundException when classpath discovery is performed.
Either way my mocking doesn't work.

Similar problem happens when multiple ears are collapsed into single classpath.ear (on tests). When multiple implementations of same business interface are present across different ears, there is not way in OpenEJB to manually pick up desired implementation.

My question is - am I doing something wrong or I'm trying to 'beat the game' and doing things which OpenEJB wasn't designed for.

The code for this example is on my github (https://github.com/kubamarchwicki/ejb-testing) if some reference is needed.

many thanks
Jakub
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

David Blevins-2
On Jun 27, 2011, at 1:44 PM, kubamarchwicki wrote:

> Here is my issue with OpenEJB. I'm note sure if what I'm trying to do is not
> possible or I'm doing something wrong.

Saw your article and I don't think you're doing anything "wrong".  Maybe the existing set of features don't fully cover what you're trying to do -- or maybe they do, but not in a convenient way.  Either way, most of the existing features came from user requests, so hopefully we can mine some gems from your experience.

> I use OpenEJB only for testing - embedded container. In the application I
> have multiple beans implementing same business interface, one main - with
> logic, few other in tests. What I'm looking for is possibility to (after
> bootstrapping container) override wired dependencies with the testing
> implementation.

I'd like to spend some time attempting to do the things you describe -- walk in your shoes, so to speak.  Might be a day or two before I can do that.  In the meantime, can you take a look at this technique.  It's how we write our internal tests and is a big influence on Arquillian -- OpenEJB was a pretty critical part of Arquillian when they were first getting it going.

  http://people.apache.org/~dblevins/application-composer/
  http://people.apache.org/~dblevins/application-composer.zip

This is the main guy to look at:

  http://people.apache.org/~dblevins/application-composer/src/test/java/org/superbiz/composed/MoviesTest.java

Basically with this approach there is zero classpath scanning.  The only thing built is what you give OpenEJB directly, regardless of what is floating around in your classpath.  It's also not really integration testing as the idea is that you isolate the component (or two) you want to test and just test that small controlled number of components.

Mixing the worlds of fully integration testing and doing this more true unit testing is certainly something I've thought of.  Making small adjustments to a large app is not yet as easy as it should be -- the alternative xml approach is only so useful.  

One thought that I've had is to maybe come up with some hybrid.  Some sort of visitor pattern where, like you mention, the test case can make programmatic changes to the application before it is deployed.

Before we actually start building anything, our "deployment" process looks like this:

    1 scan for apps in the classpath
    2 read in descriptors
    3 scan for @Stateful, @Singleton, @Stateless, @MessageDriven
    4 process annotations for known components (the above, plus those in xml)
    5 validating app compliance
    6 resolving resource references
    7 resolving ejb references
    8 turning the descriptor tree into Info objects for final assembly
    9 final validation check

Between before and after step 4 would be prime places for some developer hooks.  Before 4 you could swap out the implementations of components.  After 4 you could change any part of the metadata for an app regardless if it came from annotations or xml -- after 4 we have pulled all the annotation data out and essentially put the data in the objects we use to represent the descriptor.

One thought as to how to offer such hooks might be to do something like the ApplicationComposer but instead of @Module methods that produce (return) various things like EjbJar or SessionBean or PersistenceUnit, we instead have methods that take them as arguments (basically visitor methods).  Something like:

  @PreProcess
  public void anymethodName(EjbJar ejbJar) {
     // do anything you want to the app before we do step 4
  }

  @PostProcess
  public void anymethodName(EjbJar ejbJar) {
     // do anything you want to the app after we do step 4
  }


-David

> How I understand OpenEJB lifecycle, first ejb-jar.xml is evaluated. After
> that - class path discovery is performed. In either cases it doesn't work
> for me. When I put something like this in ejb-jar.xml a NullPointer is
> thrown (MethodController is my business service,
> AnotherTestingDisplayingService is a testing mockup)
>        <session>
>            <ejb-name>MethodController</ejb-name>
>            <ejb-ref>
>
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
>
> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>                <injection-target>
>
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>
> <injection-target-name>displayingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
>
> Sounds reasonable, MethodController is not yet present in context.
>
> On the other hand, when I fully define MethodController in ejb-jar.xml (like
> this)
> <session id="MethodController">
>            <ejb-name>MethodController</ejb-name>
>            <mapped-name></mapped-name>
>
> <business-local>pl.marchwicki.ejb.controllers.MethodControllerLocal</business-local>
>
> <ejb-class>pl.marchwicki.ejb.controllers.MethodController</ejb-class>
>            <session-type>Stateless</session-type>
>            <transaction-type>Container</transaction-type>
>            <ejb-ref>
>
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
>
> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>                <injection-target>
>
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>
> <injection-target-name>displayingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
>            <ejb-ref>
>
> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/calculatingService</ejb-ref-name>
>
> <remote>pl.marchwicki.ejb.business.CalculatingServiceLocal</remote>
>                <injection-target>
>
> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>
> <injection-target-name>calculatingService</injection-target-name>
>                </injection-target>
>            </ejb-ref>
>        </session>  
>
> I get javax.naming.NameAlreadyBoundException when classpath discovery is
> performed.
> Either way my mocking doesn't work.
>
> Similar problem happens when multiple ears are collapsed into single
> classpath.ear (on tests). When multiple implementations of same business
> interface are present across different ears, there is not way in OpenEJB to
> manually pick up desired implementation.
>
> My question is - am I doing something wrong or I'm trying to 'beat the game'
> and doing things which OpenEJB wasn't designed for.
>
> The code for this example is on my github
> (https://github.com/kubamarchwicki/ejb-testing) if some reference is needed.
>
> many thanks
> Jakub
>
> --
> View this message in context: http://openejb.979440.n4.nabble.com/override-annotation-based-configuration-with-ejb-jar-xml-tp3628804p3628804.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

kmalhi
On Wed, Jun 29, 2011 at 10:43 PM, David Blevins <[hidden email]> wrote:

> On Jun 27, 2011, at 1:44 PM, kubamarchwicki wrote:
>
>> Here is my issue with OpenEJB. I'm note sure if what I'm trying to do is not
>> possible or I'm doing something wrong.
>
> Saw your article and I don't think you're doing anything "wrong".  Maybe the existing set of features don't fully cover what you're trying to do -- or maybe they do, but not in a convenient way.  Either way, most of the existing features came from user requests, so hopefully we can mine some gems from your experience.
>
>> I use OpenEJB only for testing - embedded container. In the application I
>> have multiple beans implementing same business interface, one main - with
>> logic, few other in tests. What I'm looking for is possibility to (after
>> bootstrapping container) override wired dependencies with the testing
>> implementation.
>
> I'd like to spend some time attempting to do the things you describe -- walk in your shoes, so to speak.  Might be a day or two before I can do that.  In the meantime, can you take a look at this technique.  It's how we write our internal tests and is a big influence on Arquillian -- OpenEJB was a pretty critical part of Arquillian when they were first getting it going.
>
>  http://people.apache.org/~dblevins/application-composer/
>  http://people.apache.org/~dblevins/application-composer.zip
>
> This is the main guy to look at:
>
>  http://people.apache.org/~dblevins/application-composer/src/test/java/org/superbiz/composed/MoviesTest.java
>
> Basically with this approach there is zero classpath scanning.  The only thing built is what you give OpenEJB directly, regardless of what is floating around in your classpath.  It's also not really integration testing as the idea is that you isolate the component (or two) you want to test and just test that small controlled number of components.
>
> Mixing the worlds of fully integration testing and doing this more true unit testing is certainly something I've thought of.  Making small adjustments to a large app is not yet as easy as it should be -- the alternative xml approach is only so useful.
>
> One thought that I've had is to maybe come up with some hybrid.  Some sort of visitor pattern where, like you mention, the test case can make programmatic changes to the application before it is deployed.
>
> Before we actually start building anything, our "deployment" process looks like this:
>
>    1 scan for apps in the classpath
>    2 read in descriptors
>    3 scan for @Stateful, @Singleton, @Stateless, @MessageDriven
>    4 process annotations for known components (the above, plus those in xml)
>    5 validating app compliance
>    6 resolving resource references
>    7 resolving ejb references
>    8 turning the descriptor tree into Info objects for final assembly
>    9 final validation check
>
> Between before and after step 4 would be prime places for some developer hooks.  Before 4 you could swap out the implementations of components.  After 4 you could change any part of the metadata for an app regardless if it came from annotations or xml -- after 4 we have pulled all the annotation data out and essentially put the data in the objects we use to represent the descriptor.
>
> One thought as to how to offer such hooks might be to do something like the ApplicationComposer but instead of @Module methods that produce (return) various things like EjbJar or SessionBean or PersistenceUnit, we instead have methods that take them as arguments (basically visitor methods).  Something like:
>
>  @PreProcess
>  public void anymethodName(EjbJar ejbJar) {
>     // do anything you want to the app before we do step 4
>  }
>
>  @PostProcess
>  public void anymethodName(EjbJar ejbJar) {
>     // do anything you want to the app after we do step 4
>  }
>
This is a pretty neat idea!

>
> -David
>
>> How I understand OpenEJB lifecycle, first ejb-jar.xml is evaluated. After
>> that - class path discovery is performed. In either cases it doesn't work
>> for me. When I put something like this in ejb-jar.xml a NullPointer is
>> thrown (MethodController is my business service,
>> AnotherTestingDisplayingService is a testing mockup)
>>        <session>
>>            <ejb-name>MethodController</ejb-name>
>>            <ejb-ref>
>>
>> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
>>
>> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>>                <injection-target>
>>
>> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>>
>> <injection-target-name>displayingService</injection-target-name>
>>                </injection-target>
>>            </ejb-ref>
>>
>> Sounds reasonable, MethodController is not yet present in context.
>>
>> On the other hand, when I fully define MethodController in ejb-jar.xml (like
>> this)
>> <session id="MethodController">
>>            <ejb-name>MethodController</ejb-name>
>>            <mapped-name></mapped-name>
>>
>> <business-local>pl.marchwicki.ejb.controllers.MethodControllerLocal</business-local>
>>
>> <ejb-class>pl.marchwicki.ejb.controllers.MethodController</ejb-class>
>>            <session-type>Stateless</session-type>
>>            <transaction-type>Container</transaction-type>
>>            <ejb-ref>
>>
>> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/displayingService</ejb-ref-name>
>>
>> <remote>pl.marchwicki.ejb.view.DisplayingServiceLocal</remote>
>>                <ejb-link>AnotherTestingDisplayingService</ejb-link>
>>                <injection-target>
>>
>> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>>
>> <injection-target-name>displayingService</injection-target-name>
>>                </injection-target>
>>            </ejb-ref>
>>            <ejb-ref>
>>
>> <ejb-ref-name>pl.marchwicki.ejb.controllers.MethodController/calculatingService</ejb-ref-name>
>>
>> <remote>pl.marchwicki.ejb.business.CalculatingServiceLocal</remote>
>>                <injection-target>
>>
>> <injection-target-class>pl.marchwicki.ejb.controllers.MethodController</injection-target-class>
>>
>> <injection-target-name>calculatingService</injection-target-name>
>>                </injection-target>
>>            </ejb-ref>
>>        </session>
>>
>> I get javax.naming.NameAlreadyBoundException when classpath discovery is
>> performed.
>> Either way my mocking doesn't work.
>>
>> Similar problem happens when multiple ears are collapsed into single
>> classpath.ear (on tests). When multiple implementations of same business
>> interface are present across different ears, there is not way in OpenEJB to
>> manually pick up desired implementation.
>>
>> My question is - am I doing something wrong or I'm trying to 'beat the game'
>> and doing things which OpenEJB wasn't designed for.
>>
>> The code for this example is on my github
>> (https://github.com/kubamarchwicki/ejb-testing) if some reference is needed.
>>
>> many thanks
>> Jakub
>>
>> --
>> View this message in context: http://openejb.979440.n4.nabble.com/override-annotation-based-configuration-with-ejb-jar-xml-tp3628804p3628804.html
>> Sent from the OpenEJB User mailing list archive at Nabble.com.
>
>



--

Karan Singh Malhi
twitter.com/KaranSinghMalhi
Karan Singh Malhi
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

kubamarchwicki
In reply to this post by David Blevins-2
David Blevins-2 wrote
I'd like to spend some time attempting to do the things you describe -- walk in your shoes, so to speak.  Might be a day or two before I can do that.  In the meantime, can you take a look at this technique.  It's how we write our internal tests and is a big influence on Arquillian -- OpenEJB was a pretty critical part of Arquillian when they were first getting it going.

  http://people.apache.org/~dblevins/application-composer/
  http://people.apache.org/~dblevins/application-composer.zip
Thank you David,
That works like a charm and it's few times faster than boostrapping whole container (at least for this simple application). Little trick is - I'm using TestNG not junit on the daily basis. I'll try to have those two work together. Should not be hard

Surely, I'll follow up my writeup to describe the ApplicationComposer. It's really neat!
Jakub
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

Romain Manni-Bucau
if i remember i wrote an abstract class for testng

https://issues.apache.org/jira/browse/OPENEJB-1526

- Romain

2011/6/30 kubamarchwicki <[hidden email]>

>
> David Blevins-2 wrote:
> >
> >
> > I'd like to spend some time attempting to do the things you describe --
> > walk in your shoes, so to speak.  Might be a day or two before I can do
> > that.  In the meantime, can you take a look at this technique.  It's how
> > we write our internal tests and is a big influence on Arquillian --
> > OpenEJB was a pretty critical part of Arquillian when they were first
> > getting it going.
> >
> >   http://people.apache.org/~dblevins/application-composer/
> >   http://people.apache.org/~dblevins/application-composer.zip
> >
>
> Thank you David,
> That works like a charm and it's few times faster than boostrapping whole
> container (at least for this simple application). Little trick is - I'm
> using TestNG not junit on the daily basis. I'll try to have those two work
> together. Should not be hard
>
> Surely, I'll follow up my writeup to describe the ApplicationComposer. It's
> really neat!
> Jakub
>
> --
> View this message in context:
> http://openejb.979440.n4.nabble.com/override-annotation-based-configuration-with-ejb-jar-xml-tp3628804p3635696.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

kubamarchwicki
Romain Manni-Bucau wrote
if i remember i wrote an abstract class for testng

https://issues.apache.org/jira/browse/OPENEJB-1526

- Romain
Romain, that looks like an absolute class! I'll give it a try and share my experience as a follow up to the articles I've already written. I've already tried with JUnit and I'm excited about the results. The test are running few times faster (no need to bootstrap persistence unit on every test for example). I must admit that's something I've been looking for.

Jakub
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

David Blevins-2

On Jun 30, 2011, at 12:27 PM, kubamarchwicki wrote:

>
> Romain Manni-Bucau wrote:
>>
>> if i remember i wrote an abstract class for testng
>>
>> https://issues.apache.org/jira/browse/OPENEJB-1526

Check that in!  That's great.  Having not done a lot of work in TestNG I simply had no idea how to accomplish the same thing.  That looks great and we can probably refactor things internally for a little more reuse.

Side note to Jakub on the ApplicationComposer.  What we're doing internally is adding your test case to the app as a bean and deploying it.  It is effectively the same as creating an inner-class bean to drive testing.  The method-level services that beans get are not there yet (see the last section below), but 100% of the dependency injection that an EJB can get a test case can get too.  This is true of ApplicationComposer or use of the EJBContainer API (also detailed below).

And in terms of third-party frameworks offering this dependency injection and "portability" to test cases, I admit I scratch my head a little bit.  Dependency injection is Inversion of Control and Inversion of Control is already all about portability.  It is invisible by definition and the entire point is that you *don't* see or have a dependency on who is doing the injection.  Your only dependency is on the things you need injected -- your stuff.  So who really cares who is doing the injection -- the container itself or a third-party test framework that pulls the stuff from the container and puts it in.  Neither is less or more "portable" and ultimately what you can get injected boils down to what the container you are testing with supports.

The only real question of portability is in the bootstrapping process.  The EJBContainer API is currently the only spec standard bootstrapping mechanism we have and is only the start.  All vendors have no choice but to support it if they want to be a certified Java EE implementation -- full profile or web profile.  The more we as an industry adopt it, the more requirements we demand from it, the more things evolve and the more features get added back into spec.  The innovation of a few vendors get pushed back onto all the vendors and the level of portability increases.

The idea of a third-party framework that does the testing integration work for the vendor, taking on the work of creating and maintaining an adapter for each popular platform, is certainly interesting and can no doubt move a little quicker.  But I question its ability to persist over time.  It's a lot to maintain and there is no incentive for vendors to be anything but lazy.  Regardless, I applaud either approach -- any step forward is a good one.  It's beyond wonderful to see what can only be described as a testing renaissance happening in Java EE.

People typically don't test Spring components without Spring and if things were that easy in Java EE (via any means) people wouldn't dream of the Do It Yourself approach.  It all boils down to speed and convenience.  We're finally taking concrete steps down that path in Java EE.

> Romain, that looks like an absolute class! I'll give it a try and share my
> experience as a follow up to the articles I've already written. I've already
> tried with JUnit and I'm excited about the results. The test are running few
> times faster (no need to bootstrap persistence unit on every test for
> example). I must admit that's something I've been looking for.

Right.  And in trunk (OpenEJB 4.0) we've married this with the EJBContainer API which basically gives you the same "build your app" functionality without any test framework specific things.  Since it is not testing specific, you could use it in any kind of standalone app.  Small example of manually creating one little bean in a jar:

   http://svn.apache.org/repos/asf/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/OpenEjbContainerTest.java

Note that also shows injection of the class who bootstrapped the EJBContainer API.  You can actually get that without the cast to OpenEjbContainer by just calling `EJBContainer.createEJBContainer().getContext().bind("inject", this);`  Nearly all our examples in trunk have been ported to the EJBContainer API:

   http://ci.apache.org/projects/openejb/examples-generated/   (this little tool is two weeks young and still a work in progress)

Standardly that API has a couple ways to disable the classpath scan (the magic part).  You can pass String, String[], File or File[] as the value of the `javax.ejb.embeddable.modules` property of the `javax.ejb.embeddable.EJBContainer` API.

  - String, String[] = the module name(s) you want deployed.  Module name is as defined by the Java EE 6 rules: defaults to the directory or jar name sans the extension, but can be explicitly set in the related descriptor via the `<module-name>` element
  - File, File[] = the actual file paths of the modules you want deployed.

That still might get you more than you want -- allows you to identify modules, but doesn't allow you to be more specific and select individual components.  I hope at some point there is a standard way we can do that, but in the meantime we do have some extensions to the `javax.ejb.embeddable.modules`.

Alternatively, we will allow you to pass in any of the descriptor trees we understand -- these are the same as supported by ApplicationComposer.  Currently supported in 4.0.0-SNAPSHOT:
 
  - EjbJar
  - EnterpriseBean (convenience shorthand of EjbJar)
  - Application
  - Connector
  - Persistence
  - PersistenceUnit (convenience shorthand of Persistence)
  - Beans (aka cdi beans.xml, not well known yet)

Don't yet have support for collections of these things, but that will be there before final version.  With the ApplicationComposer you can just have several @Module methods and pass back any of the above, so building a larger app is easy.  Certainly passing a List<Object> as the value of "javax.ejb.embeddable.modules" will be supported.  But since there's already a Map being passed as the value of `EJBContainer.createEJBContainer`, there's no reason to cram everything into one key and instead we could just allow you to `map.put("myModule", ejbJar);`

Not supported yet as a `javax.ejb.embeddable.modules` value, but we will add before final and is something I would really like to add in EJB 3.2 as a standard part of the EJBContainer API is:

  - Class, Class[] = just give us the class(es) directly.  Skip the scrape and hand them right to us.  We'll treat them as if we "found" them on the classpath.  Nice thing is no vendor-specific objects and anyone should be able to support it.  Could be of limited use without descriptor data, but with a little clever thinking we can probably find a way to work that in.  A simple class that wraps Class[] and URL[] (the descriptors) would do the trick.  Anytime you introduce a new type on a spec level it is hard to keep people focused on keeping things simple, but we might be able to pull it off.  Getting the `javax.ejb.embeddable.EJBContainer` API in there at all was quite the feat and only possible because of the maturity of the InitialContext approach we had proven works.  Obviously a lot more is required beyond that simple API, but getting the entire industry to agree to support embedded EJB Containers is a game-changing step forward.

Summary: all of the above pertains to just plain old `javax.ejb.embeddable.EJBContainer` API which is not testing specific.  Applies to any EJB development where you simply do not want a server or would prefer to work in a plain Java SE environment.


Back in the testing world, there are more interesting things that can be done besides skipping the scrape and building apps in code.  Specifically, if EJB as an environment offers services like transactions and security that can be declared on individual methods of beans, why not let tests do the same?  Why not allow people to specify with an annotation on their test method if they need a transaction or not, or if the test should be executed as a particular role.  This is all in the experimental stage, but indicative of what we'd like to see in next.next. gen testing:

  // Run each test as a specific role and do your own pass/fail checking
  http://svn.apache.org/repos/asf/openejb/trunk/openejb3/container/openejb-junit/src/test/java/org/apache/openejb/junit/TestEjbSecurityRunTestAs.java

  // Run each test N times and have the framework do the pass/fail checking
  http://svn.apache.org/repos/asf/openejb/trunk/openejb3/container/openejb-junit/src/test/java/org/apache/openejb/junit/TestEjbSecurity.java

Obviously, this starts to really get at some of what makes integration testing hard which is dealing with combinations of factors.  EJB as a concept tries to take the complexity of several real world factors out of code (security, transactions, etc).  Unless there is some equally easy way to express these factors in tests, the complexity winds up in the testing code.  The two need to be at the same level.

Anyway, it's a huge evolving topic we're obviously very passionate about.  Hoping to use much of the above for documentation -- we need it -- and you're more than welcome to use any of it as well in your writings -- we need help there too :)


-David

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: override annotation based configuration with ejb-jar.xml

kubamarchwicki
Hi David,
It has been a while, but the details and suggestions on running app-composer test made my July very busy - refactoring a vast selection of OpenEJB tests (making it run significantly faster).
I like the idea of @PreProcess and @PostProcess - this looks like something I'm looking for. My intention is to leverage tools like Mockito or Easymock. I'm still not sure if that's gonna work - I hope so. At the moment I'm building inner classes, which mock certain pits and pieces of functionality and use them in application composer to build the context. This is not as flexible as I'd love to - but works better in my tests that complete classpath scanning.
What you've shown in examples from OpenEJB 4.0 looks similar and it seems sufficient for everything I can imagine. A little bit more verbose, but it's not an issue (at least from my perspective).

The other issue I was initially trying to solve, disappeared when I used app-composer approach. In my application I have multiple implementation of same business interface, deployed among multiple ears. During tests with OpenEJB I have little control over what gets injected where. Now, I can build and deploy multiple EjbJar, knowing exactly what gets wired and where.

Honestly, after this discussion and after trying out a few things I don't feel I need any other 'frameworks' and in terms of testing OpenEJB works great for me. I'll be still pushing 3.1.4 version (which is one I'm currently using) and I'm looking forward to 4.0 :-)

Once again - many thanks
--Jakub
Loading...