Showing posts with label Frameworks. Show all posts
Showing posts with label Frameworks. Show all posts

Friday, October 12, 2012

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 :-).

Tuesday, June 19, 2012

How I explained Dependency Injection to My Team

Recently our company started developing a new java based web application and after some evaluation process we decided to use Spring.

But many of the team members are not aware of Spring and Dependency Injection principles.
So I was asked to give a crash course on what is Dependency Injection and basics on Spring.

Instead of telling all the theory about IOC/DI I thought of explaining with an example.

Requirement: We will get some Customer Address and we need to validate the address.
After some evaluation we thought of using Google Address Validation Service.

 Legacy(Bad) Approach:

Just create an AddressVerificationService class and implement the logic.

Assume GoogleAddressVerificationService is a service provided by Google which takes Address as a String and Return longitude/latitude.

class AddressVerificationService 
{
   public String validateAddress(String address)
 {
 GoogleAddressVerificationService gavs = new GoogleAddressVerificationService();
  String result = gavs.validateAddress(address);  
  return result;
 }
}

Issues with this approach: 
 1. If you want to change your Address Verification Service Provider you need to change the logic.
 2. You can't Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 Due to some reason Client ask us to support multiple AddressVerificationService Providers and we need to determine which service to use at runtime.

To accomidate this you may thought of changing the above class as below:

class AddressVerificationService
{
//This method validates the given address and return longitude/latitude details.
 public String validateAddress(String address)
 {
  String result = null;
  int serviceCode = 2; // read this code value from a config file
  if(serviceCode == 1)
  {
   GoogleAddressVerificationService googleAVS = new GoogleAddressVerificationService();
   result = googleAVS.validateAddress(address);
  } else if(serviceCode == 2)
  {
   YahooAddressVerificationService yahooAVS = new YahooAddressVerificationService();
   result = yahooAVS.validateAddress(address);
  }
  return result;
 }
}

Issues with this approach: 


1. Whenever you need to support a new Service Provider you need to add/change logic using if-else-if.
 2. You can't Unit Test with some Dummy AddressVerificationService (Using Mock Objects)

 IOC/DI Approach: 

 In the above approaches AddressVerificationService is taking the control of creating its dependencies.
 So whenever there is a change in its dependencies the AddressVerificationService will change.

 Now let us rewrite the AddressVerificationService using IOC/DI pattern.

 class AddressVerificationService
 {
  private AddressVerificationServiceProvider serviceProvider;
  
  public AddressVerificationService(AddressVerificationServiceProvider serviceProvider) {
   this.serviceProvider = serviceProvider;
  }
  
  public String validateAddress(String address)
  {
   return this.serviceProvider.validateAddress(address);
  }
 }
 
 interface AddressVerificationServiceProvider
 {
  public String validateAddress(String address);
 }
 

Here we are injecting the AddressVerificationService dependency AddressVerificationServiceProvider.

Now let us implement the AddressVerificationServiceProvider with multiple provider services.

 class YahooAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using YAHOO AddressVerificationService");
   return yahooAVSAPI.validate(address);
  }  
 }

 class GoogleAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using Google AddressVerificationService");
   return googleAVSAPI.validate(address);
  }
 }
 
Now the Client can choose which Service Provider's service to use as follows:

 AddressVerificationService verificationService = null;
 AddressVerificationServiceProvider provider = null;
 provider = new YahooAVS();//to use YAHOO AVS
 provider = new GoogleAVS();//to use Google AVS
 
 verificationService = new AddressVerificationService(provider);
 String lnl = verificationService.validateAddress("HitechCity, Hyderabad");
 System.out.println(lnl);
 

For Unit Testing we can implement a Mock AddressVerificationServiceProvider.

 class MockAVS implements AddressVerificationServiceProvider
 {
  @Override
  public String validateAddress(String address) {
   System.out.println("Verifying address using MOCK AddressVerificationService");
   return "<response><longitude>123</longitude><latitude>4567</latitude>";
  }
 }
 
 AddressVerificationServiceProvider provider = null;
 provider = new MockAVS();//to use MOCK AVS  
 AddressVerificationServiceIOC verificationService = new AddressVerificationServiceIOC(provider);
 String lnl = verificationService.validateAddress("Somajiguda, Hyderabad");
 System.out.println(lnl);
 

With this approach we elemenated the issues with above Non-IOC/DI based approaches.
 1. We can provide support for as many Provides as we wish. Just implement AddressVerificationServiceProvider and inject it.
 2. We can unit test using Dummy Data using Mock Implementation.


So by following Dependency Injection principle we can create interface-based loosely-coupled and easily testable services.

Monday, August 22, 2011

Are frameworks making developers dumb?

Last week I got to take interviews to hire senior java developers with around 5 years of experience. But after the interview process is over I felt like the frameworks makes developers life easier but at the same time making them dumb.

Everyone puts almost all the new frameworks on their resume claiming they have "Strong, working experience on Spring, Hibernate, Web Services etc".

Here is how the interviews went on.

Me: You have used Spring in your latest project. What are the advantages of using Spring?
Interviewee: We can configure beans in XML and it will take care of instantiating and give it to us.

Me: If Spring is for only creating objects why is it required at all, I can directly instantiate the dependencies using "new". Why should I configure the class names in XML and get the object from Spring?

Interviewee: If tomorrow we want to create another implementation of our interface we can create new implementation and update the XML configuration to use new impl. We don't need to change Java class and compile them.
Me: But you are writing a new Java class, so obviously you need to compile the project.
Regarding XML change, 99% of the times your XML will be packaged in war or ear file.
So you will run ANT script and create the war with the all the new changes.
Then your point of "if it is XML i don't need to compile" is not a valid point.

Interviewee: Hmmm, But the Dependency Injection design pattern suggests to follow this way.
Me: OK. I am done with the interview. Our HR will get back to you. :-)

Interview with another guy:

Me: Can you explain about your latest project and what technologies have you used?
Interviewee: It is some XYZ System and we are using Spring, Hibernate, REST WebServices.
Me: Ok. Can you explain something about RESTful architecture?
Interviewee: We can develop RESTful application by using @RequestMapping(value="/url", method="POST"). And also we can use PUT, DELETE methods.
Me: That OK, but what is the concept of RESTful architecture?
Interviewee: That's what I am explaining. If you use @RequestMapping(value="/url", method="POST") you can develop RESTful application.

Me: Ok, How good are you in Hibernate?
Interviewee: I am using Hibernate for the last 2 years. I am very good in using Hibernate.
Me: What are the advantages of using Hibernate over JDBC?
Interviewee: By using we don't need to write anything to interact with database, Hibernate will take care of.
Me: How Hibernate comes to know about your project requirement?
Interviewee: If we use Hibernate it will take care saving, updating and fetching data from database.
Me: Uffffffuuuuu... OK.. In your free time do you read any technology related blogs?
Interviewee: Yeah, why not. That how I learn Hibernate in-depth.
Me : Very Good, nice talking to you. Our HR will get back to you. :-)

Interview process went on like this...

I strongly believe frameworks will increase developer productivity. But the developers should try to understand how the framework is doing the stuff. You need not learn all the internal working mechanisms of frameworks. If you are really good at Servlets and JSP then it is very easy to understand any Java Web framework like Struts, SpringMVC etc.If you aren't good at the basics then obviously for every other question reply would be.. "framework's annotation/xml will execute this"

I strongly recommend the people who want to start their career as a Java developer to work on Core Java, Servlets, JSP for sometime.Then only one can understand the frameworks in proper way.