Wednesday, November 12, 2008

HowTo Build an OSGI Enterprise Server: Entity- and EJB- Bundles

This part of the blog series „HowTo build an OSGI Enterprise Server“ will take a look at the different types of bundles we provide to the EJB3 container. The next chapter „EJB3 Container“ will show you how to use an OSGI ServiceTracker to start and initialize all the right way.

How to divide Entities and EJBs in Bundles

BTW: you should have knowledge about EJB3 and Annotations. The structure used in this server is only an example and your implementation perhaps is different. We can talk about these issues later after publishing source code. Also you can use Eclipse Link as JPA provider instead of Hibernate - EasyBeans can work with both.

We're using following types of bundles:

  • Entity - Bundles
  • EJB - Bundles
  • PersistenceContext - Bundles 
  • Business Interface - Bundles 

Entity - Bundles

@Entity, @Embeddable
You can use as much Entity - Bundles as you want - perhaps structured vertical for your different domains. These Entity - Bundles will also be used from our Rich Client, so - if you have bundle dependencies only used at server-side, make them optional.

EJB - Bundles

@Stateless and  @Stateful Beans, implementing Business - Interfaces (@Local, @Remote) depending from your requirements. 
These Bundles have dependencies to your Entity - Bundles and to the Business - Interfaces. 
Other EJBs from your PersistenceContext - Bundles can be injected like:
@EJB(mappedName) Business - Interface
The EJB - Bundles will not be used from Rich Client.

Remark: mappedName must be used at the moment, EZB cannot found the corresponding Business - Interfaces, if they are in different bundles (JIRA EZB-322)

PersistenceContext - Bundles

@Stateless Beans, containing a PersistenceContext (EntityManager) and - depending from your use-cases - implementing Business - Interfaces (@Local, @Remote).
@PersistenceContext(unit-name) points to your Persistence - Unit.
Each PersistenceContext - Bundle has a persistence.xml with attributes for the persistence-unit and also jta-data-source.
PersistenceContext - Bundles need package-imports of the used Entities and  implemented Business - Interfaces.
PersistenceContext - Bundles will not be used at Client-Side.

  1. All EJBs, belonging to a peristence-unit, must be in ONE bundle at the moment. (JIRA EZB-294)
  2. The Beans must have an EJB3.mappedName attribute: @Stateless(mappedName), otherwise because of a bug from EasyBeans (JIRA EZB-322) injected @EJB won't found them.
  3. Inside the persistence.xml all Entity- and Embeddable must be listed as class entries. EasyBeans should found the classes itself because of Annotations, but there's a bug if Entities and EJBs are in different Bundles.

Business Interface - Bundles

@Local, @Remote
The Business - Interface - Bundles can be structured and separated as you want - perhaps for different sub-applications or domains or...
These Bundles will also be used from your Rich Client.

EasyBeans Configuration

EasyBeans needs some configuration - data. If you're using an OSGI Framework Configuration you can add a VM argument: 
In this config folder you must store the easybeans.xml.
This easybeans.xml contains jdbcpool jndiName entries for each of your  Data - Sources. These values are identical with the jta-data-source, described at your  Persistence Unit inside persistence.xml of our PersistenceContext - Bundles.

Remark: The EasyBeans JDBCPool - Component must register first all Data - Sources, before you can start your PersistenceContext - Bundles. s.a. chapter „EJB3 Container“ for details on this.

openArchitectureWare - always can help if you're in trouble

This project is model-driven - details about it will be described in another blog series. Here are some small examples showing you, why I never will miss  openArchitectureWare in a project lead by me.

EasyBeans should recognize @Entity and @Embeddable automagically because of annotations - but it doesnt work through borders of bundles, so all @Entity and @Embeddable - classes have to be listed in your persistence.xml - in my ERP project this means more then 800 classen - and the data model isn't static and grows or changes depending from new use-cases and requirements.

But thanks to openArchitectureWare (oAW) we only need some lines in a template to get the needed output into the persistence.xml:

automatically all was generated from oAW and is in sync with your entity data model:

Another example: EasyBeans should be able to inject @EJB MyBusinessInterface correctly. But because of a bug this isn't possible if Business Interfaces are in another bundle and so we need the @EJB.mappedName attribute.

But with oAW its also easy: insert some text into a XPand - Template to add this attribute:

... and in your Business Interface:

Now all Beans get the mappedName attribute, the Business Interfaces get a Constant with this mappedName so you can inject easy:
@EJB(mappedName = MyInterface.EZB_MAPPED_NAME) MyInterface mi = null;

These are positive side-effects of model-driven development: developing of workarounds in hundredrs of classes are funny ;-)

BTW: my whole complex ERP - project would not be possible to be realized from me alone without oAW. You'll hear more about this in another blog series - and of course its your decision if you work model-driven or not - I only can show you my way of working.

 blog in german.

No comments: