A Developers Perspective on Spring vs JavaEE

In Java community Spring vs JavaEE is a never ending debate. In such debates people form two groups consisting of evangelists, architects and hard core fans of one platform and debate endlessly. Those who participate in the debates may be architects who are responsible for platform selection. But what would developers think about this Spring vs JavaEE debate?

I am a Java developer who uses both Spring and JavaEE and I am not part of Spring or JavaEE fan club. Here I would like to share my own thoughts on this epic Spring vs JavaEE debate.

1. Business(sometimes political) Aspects
In many organizations technology selection may not completely depends on developers choice. More specifically if you are working in so called giant enterprise organizations there are high chances that there is an Architecture Team who will decide what platform/language/framework/libraries to use in the projects.

In addition to that, large enterprises also considers the following aspects while choosing the technology platform:

  • Maturity of the platform/language/framework/libraries
  • Commercial support
  • Licensing cost etc etc

As a developer I can hardly influence the decision making process for any of the above aspects, especially when I am a developer in offshore development center. So I don’t worry too much about these things.

2. If you are really good at Spring/JavaEE then learning the other one shouldn’t be difficult
I am always surprised when someone says I am JavaEE expert but I can’t understand Spring or vice-versa. Both JavaEE and Spring work on the same core APIs (Servlet, JPA, JMS, BeanValidation etc), the difference is who is gluing the things together, Spring or AppServer.

Even though there are some different APIs for things like dependency injection (Spring DI, CDI), REST (JAX-RS, SpringMVC) etc they look and behave pretty similar to each other.

May be someone can say CDI is more typesafe than Spring DI. Doesn’t Spring and CDI behaves similarly when:

  • Injection using @Autowired or @Inject works fine if there is only one Spring/CDI Bean
  • Injection fails when there are more than one Spring or CDI bean implementations by throwing errors saying “Found more than one eligible beans that can be inject”
  • Use @Produces or @Bean annotated method to provide custom made objects as bean providers

As long as they are behaving similarly I don’t care whether they are implemented in more typesafe manner or used String based mappings in their internal implementations.

How can one be expert in Spring and can’t understand JavaEE and vice-versa?? How much time it can take for a Spring expert to learn JavaEE??!!

3. Which is more “Average Joe developer” friendly
I think by now many people should have realized that success of a technology may not be completely depends on its merits, but also based on developers adoption. The most important thing to realize is “Not every software developer is a rock star developer. There are more average joe developers than passionate, tech ninjas”. So in order to people adapt any framework it should be “Average Joe Developer” friendly.

I think Spring is doing pretty good job at it by providing more tools like SpringBoot, User Guides etc. Spring Security, Spring Integration, Spring XD, Spring Social addresses the modern business needs very well. Also think about various templates provided by Spring which makes easy to do things without worrying about boilerplate coding.

JavaEE is also doing very well by introducing JBossForge, Wildfly Swarm etc to quickly get started. I came across few JavaEE based frameworks like Picketlink which addresses Security requirements, but I felt it is much more complex than it should be.

The point I am trying to convey is “You can do pretty much everything in JavaEE that you can do with Spring”. The difference is which is giving more out-of-the-box to average joe developer.

4. Lame arguments without context
Whenever Spring vs JavaEE debate arises people form two groups and debate endlessly.  Unfortunately the debates focus on some useless or outdated points.

XML heavy: 
JavaEE fans first start saying Spring is XML heavy and I hate XML blah blah blah. If you are still using Spring older than version 2.5 and assuming it is still same XML based then my friend you should wake up and head to http://spring.io

EJBs are bad (or) JSF is bad
Spring fans jump on to bashing EJB and JSF as if they are same as EJB 2.x or JSF 1.x. If they really look at EJB 3.x and JSF 2.x then they wouldn’t argue on this at all. Don’t judge EJB 3.x with your 6 years back EJB2.x experience.

Heavy weight or light weight
My interpretation of this ‘weight’ thing is based on runtime foot print. To my knowledge, when you deploy your managed beans into JavaEE container then container will proxy it and inject all enterprise services (Transactions, Security etc) and in case of Spring it will be done by Spring AOP.
I don’t have any metrics to say which is more heavy weight Container Proxy or SpringAOP Proxy, but I guess there may not be significant difference.

Some people consider the size of war file as its ‘weight’. In that case compare (JavaEE AppServer + war) size with (SpringApp with 126 jars) and see which is light weight 🙂

JavaEE is standards based
Come on guys!!!!

Vendor lock-in
I think choosing a platform which doesn’t make you stick with one particular vendor is good. But going with an option purely based on the ability to move to a different implementation is not correct. How many times in an year you switch from one server to another? Choosing a platform which doesn’t lock you with a vendor is a ‘nice to have’ but it should not be major factor to choose your platform.

We don’t need external libraries
This is called “Arguing for the sake of arguing”. Show me any real application without having any dependencies. If you say I will develop my own logging library, I will write my own HTTP client, I will develop my own common-utilities then you need to look for a little bit more lazy architect/developers who doesn’t have “Re-invent all the wheels” sickness.

5. Don’t look at the crowd and say “You are all idiots because you are using X, you should migrate to Y”.
This is a common pattern that I observe on many community sites, especially on Reddit. Just post anything related to JavaEE vs Spring thing and there will be two groups who bash the other group like anything because other group are not using their favorite platform.

Think for a minute. If Spring is not any good why so many people use it and love it. If JavaEE is not good why so many people switch from Spring to JavaEE. There is so many good things in each platform. Respect others for choosing whatever option they choose. If possible ask them the reasons why they went with one over the other and learn if you miss anything.

Just saying “You all are idiots for not using my favorite option” doesn’t make them use your favorite technology. In fact it triggers the thought to come up with list of points why your favorite platform sucks.

If you really want them to switch to your favorite platform then show the reasons with code examples. Show them how easy it is to develop applications using your favorite platform with sample applications. Write more articles on commonly facing issues and how to resolve them. Get the “Average Joe Developer” on-board onto your favorite platform.

As an enthusiastic Java developer I read the Spring vs JavaEE discussions hoping there might be few things which I don’t know such as “in which areas one is better than the other”. But I find 70% of discussions goes on lame arguments which is not very interesting to me.

I wish Spring and JavaEE camps to fight more and more and made their platform superior than the other. End of the day, no matter who win the debate ultimately developers will have more powerful platforms.

Spring3+JPA2+JavaEE6AppServer = Confusion Over Configuration

Spring is great, JavaEE6 is great and latest JavaEE6 Application servers are also great. This post is not a rant on Spring Vs JavaEE6, but my experience of porting a Spring3+JPA2(Hibernate) application on JBoss AS-7.1 App Server.

My application requirement is very simple: Developing a couple of SOAP based webservices using Spring3.1 and JPA2(Hibernate) and host it on JBoss AS 7.1.

So I started creating a multi-module maven project with one jar module containing the service implementations using Spring & JPA and another war module which exposes those services as SOAP based webservices. But the key part is services needs to talk to multiple databases for some of the service methods.

 I am aware of JPA2 integration support from Spring without persistence.xml and cool packagesToScan attribute which makes life a bit easier. I configured 2 dataSources, 2 LocalContainerEntityManagerFactoryBeans, registered 2 JpaTransactionManagers and enabled Annotation based Transaction Management Support.

	<tx:annotation-driven transaction-manager="txnManager1"/>
<tx:annotation-driven transaction-manager="txnManager2"/>

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/><!-- This will throw error because it found multiple EntityManagerFactory beans -->

<bean id="txnManager1"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="emf1"/>

<bean id="txnManager2"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="emf2"/>

<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs1PU"></property>
<property name="dataSource" ref="dataSource1"></property>
<property name="jpaVendorAdapter">
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:showSql="${hibernate.show_sql}"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
<property name="packagesToScan" value="com.sivalabs.springdemo.entities"></property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>

</bean>

<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs2PU"></property>
<property name="dataSource" ref="dataSource2"></property>
<property name="jpaVendorAdapter">
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:showSql="${hibernate.show_sql}"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
<property name="packagesToScan" value="com.sivalabs.springdemo.entities"></property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>

</bean>

<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${node1.jdbc.driverClassName}"></property>
<property name="url" value="${node1.jdbc.url}"></property>
<property name="username" value="${node1.jdbc.username}"></property>
<property name="password" value="${node1.jdbc.password}"></property>
</bean>

<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${node2.jdbc.driverClassName}"></property>
<property name="url" value="${node2.jdbc.url}"></property>
<property name="username" value="${node2.jdbc.username}"></property>
<property name="password" value="${node2.jdbc.password}"></property>
</bean>

After this I realized to bind Entitymanager with the correct PersistenceUnit I need to give persistenceUnitName to LocalContainerEntityManagerFactoryBean.

	
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
<property name="persistenceUnits" >
<map>
<entry key="unit1" value="Sivalabs1PU"/>
<entry key="unit2" value="Sivalabs2PU"/>
</map>
</property>
</bean>

<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs1PU"></property>
<property name="dataSource" ref="dataSource1"></property>
....
....
</bean>

<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs2PU"></property>
<property name="dataSource" ref="dataSource2"></property>
....
....
</bean>

Then in my Service Bean EntityManagers and transaction managers are glued together as follows:

@Service
public class AdminUserService implements UserService
{
@PersistenceContext(unitName="Sivalabs1PU")
private EntityManager sivalabs1EM;
@PersistenceContext(unitName="Sivalabs2PU")
private EntityManager sivalabs2EM;

@Override
@Transactional("txnManager1")
public List<User> getAllUsersFromSivalabs1DB() {
return sivalabs1EM.createQuery("from User", User.class).getResultList();
}

@Override
@Transactional("txnManager2")
public List<User> getAllUsersFromSivalabs2DB() {
return sivalabs2EM.createQuery("from User", User.class).getResultList();
}

}

With this setup now I got the Exception saying “No persistence unit with name ‘Sivalabs1PU’ found“. Then after some googling I created META-INF/persistence.xml file as follows:

<persistence>

<persistence-unit name="Sivalabs1PU" transaction-type="RESOURCE_LOCAL">
</persistence-unit>

<persistence-unit name="Sivalabs2PU" transaction-type="RESOURCE_LOCAL">
</persistence-unit>

</persistence>

Now the persistence unit name error got resolved and got other Exception saying “User is not mapped [from User]“. The User class is annotated with @Entity and is in “com.sivalabs.springdemo.entities” package which I configured to “packagesToScan” attribute. I didn’t understand why “packagesToScan” attribute is not working which is working fine without persistence.xml. So for time being I configured entity classes in persistence.xml file.

<persistence>

<persistence-unit name="Sivalabs1PU" transaction-type="RESOURCE_LOCAL">
<class>com.sivalabs.springdemo.entities.User</class>
</persistence-unit>

<persistence-unit name="Sivalabs2PU" transaction-type="RESOURCE_LOCAL">
<class>com.sivalabs.springdemo.entities.User</class>
</persistence-unit>

</persistence>

Finally when I ran my JUnit Test which invokes AdminUserService methods everything looks good and working fine. Then I deployed the war file on JBoss AS 7.1 Server then again got a bunch of errors. JBoss is complaining that “Connection cannot be null when ‘hibernate.dialect’ not set” …. “[PersistenceUnit: Sivalabs1PU] Unable to build EntityManagerFactory”.

After thinking for a couple of minutes, I understood that JBoss server is trying to do what it is supposed to do with “Convention Over Configuration” rules. JBoss is trying to create EntityManagerFactory because it found META-INF/persistence.xml in classpath. But as it doesn’t contain jdbc connection details its throwing Error. 

Again after some googling I found we can rename persistence.xml to something else(spring-persistence.xml) and hook up this new name with Spring as follows:

	<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs1PU"></property>
<property name="persistenceXmlLocation" value="classpath:META-INF/spring-persistence.xml"/>
<property name="dataSource" ref="dataSource1"></property>
....
....
</bean>

<bean id="emf2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Sivalabs2PU"></property>
<property name="persistenceXmlLocation" value="classpath:META-INF/spring-persistence.xml"/>
<property name="dataSource" ref="dataSource2"></property>
....
....
</bean>

Finally I got this application working on my JBoss AS 7.1 successfully(Still I don’t know how many other holes are there that I haven’t yet found).

But here I didn’t understand few Spring concepts:
1. When I try to give persistenceUnitName why Spring is checking for that name to be existed in persistence.xml? Anyway that persistence.xml doesn’t contain anything exception the unit-name!!

2. Why packagesToScan mechanism is failing when used with persistence.xml? Is it a Spring Bug?

Everything seems to be working fine except one thing is missing, a smile on my face which usually I have when working with Spring and Tomcat 🙁

I like Spring framework very much and I am using it since 2006 and I do enjoy while writing Spring code. That doesn’t mean I don’t like CDI, EJB3, JAX-RS 🙂

 Anyway, with all the above exercise I feel like Spring3+JPA2+JavaEE6AppServer=Confusion Over Configuration and it is my(an average java developer) opinion only.

Again say one more time : Spring is great, JavaEE6 is great and latest JavaEE6 Application servers are also great :-).

RESTEasy Tutorial Part 3 – Exception Handling

 

RESTEasy Tutorial Series

RESTEasy Tutorial Part-1: Basics

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy Tutorial Part 3 – Exception Handling

Exception Handling is an obvious requirement while developing software application. If any error occured while processing user request we should show the user an error page with details like brief exception message, error code(optional), hints to correct the input and retry(optional) and actual root cause(optional). This is applicable to RESTful web services also.

But putting try-catch-finally blocks all around the code is not a good practice. We should design/code in such a way that if there is any unrecoverable error occured then the code should throw that exception and there should an exception handler to catch those exceptions and extract the error details and give a proper error response to the client with all the error details.

RESTEasy provides such ExceptionHandler mechanism which simplifies the ExceptionHandling process.

In this part I will show you how we can use RESTEasy’s ExceptionHandlers to handle Exceptions.

Step#1: Create Application Specific Exceptions.

Step#2: Create ExceptionHandlers by implementing ExceptionMapper interface.

Step#3: Update UserResource.getUserXMLById() method to validate user input and throw respective exceptions.

Step#4: Test the UserResource.getUserXMLById() service method by issueing following requests.


Important things to note:
As Spring is creating the necessary objects we should let Spring know about @Provider classes to get them registered with RESTEasy. We can do this in two ways.

a)Annotate Provider classes with @Component

b)Using component-scan’s include-filter.

<context:component-scan base-package=”com.sivalabs.springdemo”>
         <context:include-filter expression=”javax.ws.rs.ext.Provider” type=”annotation”/>
</context:component-scan>

RESTEasy Tutorial Part-2: Spring Integration

 

RESTEasy Tutorial Series

RESTEasy Tutorial Part-1: Basics

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy Tutorial Part 3 – Exception Handling
RESTEasy provides support for Spring integration which enables us to expose Spring beans as RESTful WebServices.

Step#1: Configure RESTEasy+Spring dependencies using Maven.

Step#2: Configure RESTEasy+Spring in web.xml


		
   
    org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
  
  
    org.jboss.resteasy.plugins.spring.SpringContextLoaderListener
  
  
    Resteasy
    org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
  
  
    Resteasy
    /rest/*
  
  
    contextConfigLocation
    classpath:applicationContext.xml
  
  
    resteasy.servlet.mapping.prefix
    /rest
  

  
        resteasy.scan
        false
    

Step#3: Create a Spring Service class UserService and update UserResource to use UserService bean.

Step#4: Same JUnit TestCase to test the REST Webservice described in Part-1.

Important Things to Keep in mind:
1. org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap Listener should be registered before any other listener.
2. You should configure resteasy.servlet.mapping.prefix <context-param> if the HttpServletDispatcher servlet url-pattern is anything other than /*
3. While using Spring integration set resteasy.scan to false or don’t configure resteasy.scan parameter at all.
Otherwise you may get REST Resource instances(UserResource) from RestEasy instead of Spring container. While running JUnit Tests I observed this random behavior.

4. You should register REST Resource as Spring bean by annotating with @Component or @Service.

RESTEasy Tutorial Part-1: Basics

 

RESTEasy Tutorial Series

RESTEasy Tutorial Part-1: Basics

RESTEasy Tutorial Part-2: Spring Integration

RESTEasy Tutorial Part 3 – Exception Handling
RESTEasy is a JAX-RS implementation from JBoss/RedHat and is in-built in JBoss 6 onwards.
Here I am going to show you how to develop a Simple RESTful Web Services application using RESTEasy and JBossAS7.1.1.FINAL.

Step#1: Configure RESTEasy dependencies using Maven.

Step#2: Configure RESTEasy in web.xml

Step#3: Create User domain class, MockUserTable class to store User objects in-memory for testing purpose and UserResource class to expose CRUD operations on User as RESTful webservices.

Step#6: JUnit TestCase to test the REST Webservice.

Step#7: To test the REST service we can use the REST Client Tool. 
You can download REST Client Tool at http://code.google.com/a/eclipselabs.org/p/restclient-tool/

Important Things to Keep in mind:
1. org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap Listener should be registered before any other listener.

2. You should configure resteasy.servlet.mapping.prefix <context-param> if the HttpServletDispatcher servlet url-pattern is anything other than /*


3. Keep visiting my blog 🙂