Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modularize an Enterprise Application with OSGi and EE6?

I know that there are already some questions related to this topic but I couldn't find a real solution yet.

Currently I am developing applications with EE6, using JPA, CDI, JSF. I would like to take a more modular approach than packaging everything into a WAR or EAR and deploy the whole thing on an Application Server.

I am trying to design my applications as modular as possible by separating a module into 3 maven projects:

  • API - Contains the interfaces for (stateless) services
  • Model - Contains the JPA Entities for the specific module
  • Impl - Contains the implementation of the API, mostly CDI beans

The view logic of every module is currently bundeled within a big web project, which is ugly. I already thought of web fragmets, but if I spread my bean classes and xhtml files in jar files, I would have to implement a hook so that the resources could be looked up by a parent web application. This kind of solution would at least enable me to have a fourth project per module that would contain all the view logic related to the module, which is a good start.

What I want is not only that I can have those 4 kinds of projects, but also that every project is hot swappable. This led me to OSGi, which was at first really cool until I realized that the EE6 technologies are not very well supported within an OSGi Container.

JPA

Let's look at JPA first. There are some tutorials[1] around that explain how to make a JPA enabled OSGi Bundle, but none of these tutorials shows how to spread entities into different bundles(the model project of a module). I would want to have for example three different modules

  • Core
  • User
  • Blog

The model project of the blog module has a (compile-time)dependency on the model project of user. The model project of the user module has a (compile-time)dependency on the model project of core.

How can I make JPA work in such a scenario without having to create a Persistence Unit for each model project of a module? I want one persistence unit that is aware of all entities available at runtime. The model projects in which the entities are should of course be hot swappable. Maybe I will need to make a separate project for every client that imports all the needed entities of the projects and contains a persistence.xml that includes all necessary configuration things. Are there any available maven plugins for building such a projects or even other approaches to solve that issue?

CDI

CDI is very nice. I really love it and I don't want to miss it any more! I use CDI extensions like MyFaces CODI and DeltaSpike which are awesome! I inject my (stateless) services into other services or into the view layer which is just great. Since my services are stateless it should not be a problem to use them as OSGi Services, but what about CDI integration in OSGi? I found a glassfish CDI Extension[2] that would the injection of OSGi Services into CDI beans, but I also want may OSGi Services to be CDI beans. I am not totally sure how to achive that, probably I would have to use the BeanManager to instantiate the implementations and then register every implementation for its interface in the ServiceRegistry within a BundleActivator. Is there any standard way for doing that? I would like to avoid any (compile-time)dependencies to the OSGi framework.

I would also like to use my services just like I use them right now, without changing anything(implementations not annotated and injection points not qualified). There is a JBoss Weld extension/sub project[3] that seems to target that issue but it seems to be inactive, i can't find any best practices or how-tos. How can I leave my implementation as it is but still be able to use OSGi? I mean it would not be a big deal to add an annotation to the implementations since every implementation is already annotated with a stereotype annotation, anyway I would like to prevent that.

JSF

As mentioned before I would like to be able to spread my view logic module wise. As far as I know this is not really possible out of the box. Pax Web[4] should solve that somehow, but I am not familiar with it.

I would like to have a project "CoreWeb" in the module "core" that contains a Facelet template, let's call it "template.xhtml". A JSF page in a project called "BlogWeb" in the module "blog" should then be able to reference that template and apply a composition.

To be able to extend the view I would introduce a java interface "Extension" that can be implemented by a specific class of a module. A controller for a view would then inject all implementations of the extension. An extension would for example provide a list of subviews that will be included into a main view.

The described extension mechanism can be implemented easily, but the following requirements must be fulfilled:

  • When adding new OSGi Bundles to the application server, the set of available extensions might change, the extensions must be available for the controller of the view.
  • The subviews(from a separate bundle) which should be included into a main view should be accessible.

The concept of a single host but multiple slice applications of Spring Slices[5] is very interesting, but seems limited to Spring DM Server and the project also seems to be inactive.

Summary

After all the examples and behaviors I described I hope that you know what I would like to achive. It's simply an EE6 App that is very dynamic and modularized.

What I look for at the end is at least documentation on how to get everything running as I would expect it or even better an already working solution!

[1] http://jaxenter.com/tutorial-using-jpa-in-an-osgi-environment-36661.html

[2] https://blogs.oracle.com/sivakumart/entry/typesafe_injection_of_dynamic_osgi

[3] http://www.slideshare.net/TrevorReznik/weldosgi-injecting-easiness-in-osgi

[4] http://team.ops4j.org/wiki//display/paxweb/Pax+Web

[5] https://jira.springsource.org/browse/SLICE

like image 399
Christian Beikov Avatar asked Jul 01 '12 18:07

Christian Beikov


1 Answers

To answer some of your questions, using a single persistence unit but spreading your entities across multiple bundles is not recommended, but may occasionally work. However, if your entities are so closely related that they need to share a persistence unit, splitting them across modules may not make sense. Also, don't forget you can handle compile-time dependencies by separating the implementation and interface for each entity - interface and implementation need not be in the same bundle.

For dependency injection, you may like Blueprint. Several implementations are available and most application servers with enterprise OSGi support support Blueprint out of the box. It uses XML to add metadata, so classes themselves won't need any modification.

like image 99
Holly Cummins Avatar answered Oct 02 '22 14:10

Holly Cummins