Welcome!

Java IoT Authors: Pat Romanski, Zakia Bouachraoui, William Schmarzo, Elizabeth White, Yeshim Deniz

Related Topics: Java IoT, IBM Cloud

Java IoT: Article

Spring and EJB 3.0 in Harmony

In search of the best of both worlds

The new EJB 3.0 specification supports some notion of dependency injection via annotations. As an avid Spring user, I'm used to configuring fine-grained beans with Spring bean factories and XML. How does EJB 3.0 compare? More importantly, can we use EJB 3.0 POJOs and Spring POJOs side-by-side in applications? In this article, I'll try to answer those questions based on my own investigations and experiences. As it turns out, using a versatile application server like the JBoss Application Server (AS), Spring and EJB 3.0 POJOs can co-exist in harmony in your applications.

EJB3 Dependency Injection
In EJB 3.0 it's fairly easy to inject Java EE components into an EJB object using various annotations provided by the specification. @Resource is available to inject things like datasources and JMS destinations. @EJB is there to get references to other EJBs. @PersistenceContext can get you a reference to the EntityManager service. You can use these annotations to inject directly into the field of your EJB, or you can apply them on setter methods. Here are some examples:

@Stateful
public class ShoppingCartBean implements ShoppingCart {
    @Resource(name="DefaultDS") private DataSource ds;
    @EJB private CreditCardProcessor ccp;

    EntityManager em;

    @PersistenceContext(unitName="orderdb")
    public void setEntityManager(EntityManager em) {
      this.em = em;
...
}

For developers who don't want to use annotations to inject components, EJB 3.0 provides an XML alternative to injection annotations:

<ejb-ref>
    <ejb-ref-name>ejb/CreditCardProcessor</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref/type>
    <local>com.acme.CreditCardProcessor</local>
    <ejb-link>CreditCardEJB</ejb-link>
    <inject-target>ccp</inject-target>
</ejb-ref>

Great! So we have two ways of injecting dependencies in EJB 3.0. However, one big problem with EJB 3.0 dependency injection is that there's no way of configuring, defining, and injecting plain Java beans. You can only inject Java EE component types and <env-entry> only lets you inject primitive types. Sure, EJBs look a lot like POJOs and JBoss has the concept of a @Service bean, which is a singleton, but do we really have to define and inject these component objects that have to run in containers? And what about beans from third-party libraries and pre-existing code. There must be something better! Could it be JNDI registration? Maybe, but who will instantiate and construct our beans? Really this is what Spring's dependency injection is all about. But how do we get Spring's beans into an EJB3 container?

Spring and EJB3 - Synergy or Superfluous?
To integrate Spring beans with EJBs, the application server plays the central role since it can deploy both components. JBoss AS seems to be the best platform here because it was the first application server to support EJB 3.0 and it is an Open Source product. More importantly, JBoss AS's microkernel architecture is flexible enough to create any package/component type that can be deployed in the JBoss runtime. JBoss AOP and interceptor technology could be used to glue custom behavior into POJOs and/or EJBs.

So I decided to write a Spring deployer for JBoss AS. In the rest of the article, I'll discuss exactly what I did and how you can use the deployer. As it turns out, there really is synergy between Spring and JBoss EJB 3.0. Developers can have the best of both worlds.

JBoss AS Deployers
The first challenge is to package Spring into a deployable unit to eliminate the bootstrapping code that's required in most Spring applications. The deployer should work with a custom Spring archive type in much the same way Java EE has .EARs and .WARs. You can define new archive types in JBoss by writing a JBoss Deployer.

When JBoss boots up, it scans the deploy directory for available packaged components that are JBoss services or your packaged applications. JBoss Deployers are responsible for managing these packaged components. Their purpose is to understand deployment descriptors and archive formats so they can be deployed into the JBoss application server at runtime. Deployers are also responsible for creating classloaders for packaged component and managing hot deployment. There's a specific deployer service for each component type in JBoss: enterprise archives (.ear), Web archives (.war), EJB archives (.jar), datasources (-ds.xml), Hibernate archives (.har), etc. I wanted to be able to define a Spring archive (.spring) that would look like this:

myapp.spring/
    org/acme/MyBean.class
    META-INF/spring.xml

It would really look like an EJB jar, but instead of a ejb-jar.xml deployment descriptor, one would be specific to Spring. The JBoss Spring deployer recognizes the myapp.spring deployment, parses the deployment descriptor to create a Spring bean factory, and registers that Spring bean factory under some JNDI name so that it can be looked up and used by other applications. And if this archive was removed, JBoss should destroy the bean factory and unregister it from JNDI. Basically, the goal is to let Spring bean factories be hot-deployable in a JBoss environment.

JBoss has an abstract API for writing new deployers and it was very simple to write a Spring-based archive type. JBoss's deployer API provides a simple abstract class - org.jboss.deployment.SubDeployerSupport - that I used to implement my Spring Deployer. One simply has to implement or override a few methods to get things working. Let's look at those methods:

   protected void initializeMainDeployer() {
     setSuffixes(new String[]{".spring", "-spring.xml"});
     setRelativeOrder(350);
   }

   /* @return True if this deployer
   * can deploy the given DeploymentInfo.
   * @jmx:managed-operation
   */
   public boolean accepts(DeploymentInfo di) {
     String urlStr = di.url.toString();
     return urlStr.endsWith(".spring") || urlStr.endsWith(".spring/") ||
     urlStr.endsWith("-spring.xml");
   }

This code is trivial but it's the core of determining if a deployed component is a Spring component. Each JBoss deployer is asked if it accepts a given archive for deployment. This code specifies that the Spring Deployer excepts file names that end with .spring or -spring.xml. JBoss has a default ordering schema when it deploys packages. Since deployers are themselves packaged components, they tell the JBoss runtime what relative order their component type should be deployed in as shown in Listing 1.

As I said before, JBoss deployers support the hot redeployment of your custom component type at runtime. To enable this, you have to give JBoss a URL to watch to see if the timestamp on this file changes at runtime. Our deployer will support raw Spring XML files, .spring JAR archives, and exploded .spring archives. The init() method above sets up the watch URL as shown in Listing 2.

Deployers create() method calls BeanFactoryLoader's create method, which is responsible for managing our different Spring bean factories. When instantiating beans in a new bean factory we make sure that newly created beans are loaded by a global scope classloader. Normal JNDI bindings require a serializable object, which is unusable for our Spring bean factory. JBoss provides a JNDI ObjectFactory implementation that lets us store objects in a non-serializable form in a local JNDI context. The binding will only be valid as long as our bean factory is deployed.

Since we'd like to hot deploy many different Spring archives, each of them must be uniquely represented in our environment. For that purpose, JNDI will be used as a registry for these deployments. But where can we get our local JNDI name? By default, this JNDI name is obtained from the archive's file name: <name>.spring or <name>-spring.xml. But since it's also possible for each bean factory to have parent bean factory, there should be a way to define this parent's name too. This can be done in Spring's beans xml descriptor in description tag as shown in Listing 3.

We are parsing this description tag and looking for a regular expression pattern of 'BeanFactory=(<name>)' and 'ParentBeanFactory=(<name>)' so see Listing 4.

Every time a Spring component is undeployed, we get the corresponding Bean factory through the URL string key in our bean factory map. We remove the map entry, destroy the bean factory singletons, and unbind it from JNDI. When undeploying components be careful of the bean factory hierarchy; don't undeploy some other component's parent bean factory. When shutting down, JBossAS undeploys components in reverse order, which is the right behavior for our child-parent bean factory hierarchy.

More Stories By Ales Justin

Ales Justin is a Java developer at Genera Lynx d.o.o. He's also a JBoss contributor and committer.

Comments (1)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


IoT & Smart Cities Stories
Tapping into blockchain revolution early enough translates into a substantial business competitiveness advantage. Codete comprehensively develops custom, blockchain-based business solutions, founded on the most advanced cryptographic innovations, and striking a balance point between complexity of the technologies used in quickly-changing stack building, business impact, and cost-effectiveness. Codete researches and provides business consultancy in the field of single most thrilling innovative te...
Darktrace is the world's leading AI company for cyber security. Created by mathematicians from the University of Cambridge, Darktrace's Enterprise Immune System is the first non-consumer application of machine learning to work at scale, across all network types, from physical, virtualized, and cloud, through to IoT and industrial control systems. Installed as a self-configuring cyber defense platform, Darktrace continuously learns what is ‘normal' for all devices and users, updating its understa...
At CloudEXPO Silicon Valley, June 24-26, 2019, Digital Transformation (DX) is a major focus with expanded DevOpsSUMMIT and FinTechEXPO programs within the DXWorldEXPO agenda. Successful transformation requires a laser focus on being data-driven and on using all the tools available that enable transformation if they plan to survive over the long term. A total of 88% of Fortune 500 companies from a generation ago are now out of business. Only 12% still survive. Similar percentages are found throug...
CloudEXPO has been the M&A capital for Cloud companies for more than a decade with memorable acquisition news stories which came out of CloudEXPO expo floor. DevOpsSUMMIT New York faculty member Greg Bledsoe shared his views on IBM's Red Hat acquisition live from NASDAQ floor. Acquisition news was announced during CloudEXPO New York which took place November 12-13, 2019 in New York City.
OpsRamp is an enterprise IT operation platform provided by US-based OpsRamp, Inc. It provides SaaS services through support for increasingly complex cloud and hybrid computing environments from system operation to service management. The OpsRamp platform is a SaaS-based, multi-tenant solution that enables enterprise IT organizations and cloud service providers like JBS the flexibility and control they need to manage and monitor today's hybrid, multi-cloud infrastructure, applications, and wor...
The Master of Science in Artificial Intelligence (MSAI) provides a comprehensive framework of theory and practice in the emerging field of AI. The program delivers the foundational knowledge needed to explore both key contextual areas and complex technical applications of AI systems. Curriculum incorporates elements of data science, robotics, and machine learning-enabling you to pursue a holistic and interdisciplinary course of study while preparing for a position in AI research, operations, ...
Codete accelerates their clients growth through technological expertise and experience. Codite team works with organizations to meet the challenges that digitalization presents. Their clients include digital start-ups as well as established enterprises in the IT industry. To stay competitive in a highly innovative IT industry, strong R&D departments and bold spin-off initiatives is a must. Codete Data Science and Software Architects teams help corporate clients to stay up to date with the mod...
Atmosera delivers modern cloud services that maximize the advantages of cloud-based infrastructures. Offering private, hybrid, and public cloud solutions, Atmosera works closely with customers to engineer, deploy, and operate cloud architectures with advanced services that deliver strategic business outcomes. Atmosera's expertise simplifies the process of cloud transformation and our 20+ years of experience managing complex IT environments provides our customers with the confidence and trust tha...
With the introduction of IoT and Smart Living in every aspect of our lives, one question has become relevant: What are the security implications? To answer this, first we have to look and explore the security models of the technologies that IoT is founded upon. In his session at @ThingsExpo, Nevi Kaja, a Research Engineer at Ford Motor Company, discussed some of the security challenges of the IoT infrastructure and related how these aspects impact Smart Living. The material was delivered interac...
Intel is an American multinational corporation and technology company headquartered in Santa Clara, California, in the Silicon Valley. It is the world's second largest and second highest valued semiconductor chip maker based on revenue after being overtaken by Samsung, and is the inventor of the x86 series of microprocessors, the processors found in most personal computers (PCs). Intel supplies processors for computer system manufacturers such as Apple, Lenovo, HP, and Dell. Intel also manufactu...