Posts Tagged ejb3
Enterprise Javabeans 3 in OSGi — part 2
Posted by admin in Uncategorized on January 29th, 2009
This blog picks up on some unfinished items mentioned in the first blog. More specifically, this blog will focus on:
- auto-injecting session beans;
- entity-only bundles;
- transaction rollback.
Note that if the reader wants to run the example source, he or she is referred to the aformentioned previous blog in which more information on setting up the environment and getting the sources to compile/run can be found. To get the samples running, you always need to start ezb-command.jar and entitybeans.jar. Besides those 2 bundles, you either need to start combinedbean.jar (includes 2 stateless beans) or statelessbean1.jar and statelessbean2.jar (both bundles contain 1 stateless bean).
Auto-injecting session beans
In EJB3 (and therefore also in EZB) it is possible to inject a reference to a session bean through using the ‘@EJB’ annotation. When using this annotation, you can supply the product-specific name of the EJB to which it should be mapped (could be any kind of name – even though it is often a JNDI one). As it turns out, EZB almost completely supports this feature; both when the EJB to be injected is defined within the same bundle (use combinedbean.jar) and when it is defined in a different bundle (use statelessbean1.jar and statelessbean2.jar) the reference is injected properly and no lookup takes place:
@EJB(mappedName="SL2")
private Stateless2Remote m_stateless2 = null;
@EJB
private Stateless2Remote m_stateless2NotAutoInjected = null;
// ... and some code using it:
if (m_stateless2 == null) {
// '@EJB' injection did not take place, performing lookup
try {
m_stateless2 = (Stateless2Remote)new InitialContext().lookup(
String.format("%s_%s@Remote", "net.luminis.ezb.stateless2.impl.Stateless2Impl", Stateless2Remote.class.getName()));
} catch (NamingException e) {
e.printStackTrace(); // lookup failed.
}
}
Note though, that the mappedName must be set both here and in the implementation of the session bean to be injected. If this is not done, EZB cannot find/inject it. I.e. in the code above, at the point where m_stateless2 has been set, the member variable m_stateless2NotAutoInjected is still null.
Entity-only bundles
When deploying ones bundles you’re likely to combine related functionality. It’s possible to simply put everything in a single bundle, but not desirable; the more fine-grained your design, the easier it is to re-use a specific bit of functionality. When you decide to define an entity-only bundle, EZB requires that you include the line
net.luminis.ezb.entitybeans.Kangaroo
both in persistence.xml of the entity-bundle, but also in all bundles using the entity-bundle. This inconvenience may be corrected, but for now, it’s not a very flexible way of working; when you add an entity bean to your entity-bundle, you not only have to update the persistence.xml in that bundle, but also in all bundles using it!
Rollback
Finally, the source code attached to this blog also includes an example of how EZB handles a transaction rollback. It is possible to trigger such a rollback by using:
m_sessionContext.setRollbackOnly();
to signal the session to perform a rollback of every action associated with the current transaction. In this example the functionality is illustrated through using the command
ezb use_injected_max
which not only uses an injected session bean to create a Kangaroo entity, but also triggers a rollback if 4 Kangaroos have already been created. (Check the methods addKangaroo() and addKangarooWithMaximumCheck() in Stateless2Impl to find out more.
Enterprise Javabeans 3 in OSGI
Posted by Peter Doornbosch in Uncategorized on December 19th, 2008
Previous blogs (look here and here) have shown that it’s fairly easy to use (open)JPA within OSGi. Moving on on this path of attempting persistence solutions for OSGi led to an encounter with Easybeans (EZB from now on), an Enterprise Javabeans 3 (EJB3) container for OSGi.
This blog assumes that the felix 1.4.0 environment is used. All source code used and all relevant bundles can be found in this zip.
Some of the reasons EJB3 can be of interest when moving beyond what JPA has to offer:
- container managed transactions;
- dependency injection.
For more detailed information on the advantages of EJB3, refer to this article on javaworld
Using EZB within an OSGi context may be of interest to you if you’re working with an:
- EJB3 environment and you’re thinking about migrating towards OSGi;
- OSGi environment, but you don’t have a satisfactory solution for handling persistency issues.
In this blog we will use a simple example that uses some basic EJB3 functionality; we’ll use a command line client that connects to a stateless session bean. The session bean is able to interact with an entity bean called Wombat and is able to create, update and delete (Wombat) entities. We’ll walk through the specifics of each step below.
In order to execute a command, the client first has to connect to (i.e. obtain a reference to) the stateless session bean (EzbCommand.java):
private static final String STATELESS_REMOTE = "net.luminis.ezb.example1.stateless.StatelessRemote";
public void execute(String commandLine, PrintStream out, PrintStream err) {
ServiceReference ref = m_bundleContext.getServiceReference(STATELESS_REMOTE);
m_stateless = (StatelessRemote)m_bundleContext.getService(ref);
EZB registers each stateless session bean as an OSGi service when the bundle that contains the service (and using the org.ow2.easybeans.osgi.ejbjar.Activator) is started. Because of this, it is possible to use the service without EJB3/EZB specific code in the client or the service interface, even though you can still use JNDI to lookup the service. When trying this, be warned that there’s a class loader issue. When dealing with stateful beans, this mechanism does not work and a JNDI lookup must always be used.
Following that, the session bean receives a command from the client, e.g. a ‘create’ command. StatelessImpl.java then picks up the command and creates a new Wombat object with the supplied values. Once that is done, it uses the EntityManager injected into the implementation by EZB (because of the @PersistenceContext annotation – default EJB3 behaviour) to persist the newly created Wombat entity:
@PersistenceContext
private EntityManager m_entityManager = null;
public void createWombat(int id, String name) {
Wombat entity = new Wombat();
entity.setId(id);
entity.setName(name);
m_entityManager.persist(entity);
System.out.println("Created entity bean: " + findWombat(id));
The entity bean used (defined in Wombat.java) contains three EJB3 annotations, denoting it as an entity bean (’@Entity’), indicating which table to create/use for the entity (’@Table’) and indicating which of the bean’s attributes can be used as its primary key (’@Id’):
@Entity
@Table(name = "WOMBATS")
public class Wombat implements Serializable {
// [cut some code]
@Id
public int getId() {
return m_id;
}
Update the Felix configuration
Once again, please note that a felix 1.4.x environment should be used. For more information on previous releases, refer to the README in the zip file. In order to start the EZB bundles, a few changes need to be made in the configuration.
A pre-configured conf/config.properties file can be downloaded from here.
Of course, you can also apply the required changes yourself; an overview of the changes that need to be applied to the conf/config.properties file will follow.
Note that you’ll need the file config.properties of a previous release to copy two specific configuration entries: ‘org.osgi.framework.system.packages’ and ‘jre-1.x’ (depending on the JRE used, this is a list of packages that are exported by default).
Now, edit the config.properties of your newly installed Felix configuration and:
- Uncomment the ‘org.osgi.framework.system.packages’ entry and set the value to the one copied from a previous release.
- Add the complete ‘jre-1.x’ entry to (the bottom of) the file.
The ‘org.osgi.framework.system.packages’ entry should now look something like:
org.osgi.framework.system.packages=org.osgi.framework; version=1.4.0, \
org.osgi.service.packageadmin; version=1.2.0, \
org.osgi.service.startlevel; version=1.1.0, \
org.osgi.service.url; version=1.0.0, \
org.osgi.util.tracker; version=1.3.3 \
${jre-${java.specification.version}}
Note that the last line (with the ${jre-${java.specification.version}} construct) includes all items that are set in the copied ‘jre-1.x’ configuration and that this means that you must have at least 1 section in your config file that starts like:
jre-1.5=, \ javax.accessibility; \
Also, add the sun.rmi packages to the config.properties file, which can now be done more cleanly through:
org.osgi.framework.system.packages.extra= \ sun.rmi.server; \ sun.rmi.transport; \ sun.rmi.registry;
Finally, make sure Felix only logs a warning if it encounters unsupported fragment behavior through uncommenting the line with the felix.fragment.validation option:
felix.fragment.validation=warning
Download the EZB bundles
The required easybean jars can be downloaded from here. This blog is based on usage of the ‘1.1.0-M1′ release, select that release (or possibly a newer release) and then download the package available under “OSGi bundles of EasyBeans”. Unzip the file and note the location of the ‘bundles’ folder.
Install the EZB bundles
Note that this this step should be performed using a felix-1.0.x configuration or a felix-1.4.x configuration only!
In order to install the bundles, start Felix (make sure you’re using the updated configuration!) and execute the following commands in Felix:
-> cd file:/<absolute_path_to_bundle_folder>/ -> start org.apache.felix.configadmin-1.0.4.jar -> start org.apache.felix.dependencymanager-1.1.0-2008.07.10.jar -> start org.apache.felix.log-0.9.0-incubator-2007.12.14.jar -> start org.apache.felix.scr-1.0.6.jar -> start ow2-bundles-externals-commons-logging-1.0.8.jar -> start ow2-bundles-externals-commons-modeler-1.0.8.jar -> start ow2-util-event-api-1.0.8.jar -> install ow2-util-event-impl-1.0.8.jar -> start ow2-util-jmx-api-1.0.8.jar -> install ow2-util-jmx-impl-1.0.8.jar -> start slf4j-api-1.5.2.jar -> start slf4j-jcl-1.5.2.jar -> install easybeans-core-1.1.0-M1.jar -> install easybeans-component-carol-1.1.0-M1.jar -> install easybeans-component-jdbcpool-1.1.0-M1.jar -> install easybeans-component-joram-1.1.0-M1.jar -> install easybeans-component-jotm-1.1.0-M1.jar -> install easybeans-component-quartz-1.1.0-M1.jar -> install easybeans-component-hsqldb-1.1.0-M1.jar -> install easybeans-agent-1.1.0-M1.jar
Once all these bundles are Active or Installed, start the easybeans-agent bundle. Once that bundle is Active, all bundles should be. Now you can start the ezb-command.jar and the statelessbean.jar bundles (same command structure as above). If you want to build the bundles yourself, copy the file easybeans-core-1.1.0-M1.jar from the ezb bundles dir and use ant to create the bundles:
cd <example1-location> cp <ezb-bundledir-location>/easybeans-core-1.1.0-M1.jar lib ant clean bundle.all
Once that is done, you can use the jars that can be found in the output dir.
An interesting point to note for this section is the use of the ‘easybeans-agent’ bundle. This bundle is used to stop and start the ‘ow2-util-event-impl’, the ‘ow2-util-jmx-impl’, the ‘easybeans-core’ and all ‘easybeans-component’ bundles in the right order (also refer to ‘issues encountered’ section below).
Issues encountered
- When a bundle defines an entity bean in an exported package, it must import the package ‘javassist.util.proxy’ with ‘optional’ resolution;
- The fact that EZB uses the easybeans-agent instead of using dependencies was often a source of confusion, if not errors: it felt like the startup order could not always be reproduced and only by stopping the agent, shutting down the framework and restarting both, could problems be resolved;
- Running a client from the outside (not deployed in osgi / running in another JVM) that attempts to lookup (JNDI) a session bean was a real bother (and is therefore not included in this blog);
- Injecting a session bean service that is not defined in the same bundle is not (yet) possible;
- When using entity beans defined in a separate bundle, it is required to include the entity class name to be used both in the entity bundle itself and the bundle using it;
Maybe a follow-up of this blog will elaborate on the last two issues when moving on from using a single bundle to using multiple bundles.
Conclusion
All in all, the ability to use EJB3 related features from within OSGi is definitely a good thing, even though there’s a couple of usability issues to take into account still. Keeping in mind that the product is still in development and that the support is very good (when posting a question in the ow2 mailing, a response will usually follow within a day, if not within the hour), the EZB container is definitely one to keep an eye on!
