Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Friday, September 18, 2015

Spring Scopes – Decoupling code

Spring Scopes – Decoupling code


The Scenario

I have an application that has a lot of classes – more than 10. To simplify the issue, let’s say that I have a system that represents a school. So I will have a school class, a room class, teacher and all the rest, for example:
class School(){
  val classes : List[Class]
  def gotMoney(total: int)
}
class Class(){
  val teachers: List[Teacher]
  def updateTeacher(raise: int)
}
class Teacher(){
  def updateTeacherSalary(raise: int)
}

So we have in place - a school that has a list of classes that each has a list of teachers. The normal flow is that the school gets money and wants to give it to each teacher. So we have a method to pass the information from the School to the Class and then to each teacher.
Let’s say that I have a web application that calls the system, and we want to add a profile parameter that is sent during run time so that we can filter which teacher’s get a raise and which don’t.
How do we pass this new parameter from the Web API to the teacher class?

The Solution


Strait forward

A classic scenario is to add a new parameter “profile” to all the methods that need the profile. The limitation of this way is that we might want to add more than one parameter. In addition this is a legacy application that has a lot of spaghetti, so this would mean adding the parameter to a lot of methods that don’t really need to know about this.
What we really need is a way for a bunch of parameters to be entered in the Web API level and then be available to other places of code.

Scope Solution

Assumptions

The current assumption is that we have spring in place and that most of the service classes are spring beans.
So the actual solution is to create a session bean with scope prototype so that   we have a new bean each time that we need it. The bean is created on the Web API level and populated with the values, then in the lower level API the services that needs the new parameters will request the same prototype bean and get the values.
By using the prototype bean we also insure that are application can support multithreading and keep multiple instances of each session.

Standard web solution

If each bean will inject a standard prototype bean then each inject will get a new bean and the values will not persist. What we want is create only one bean per http request. For this spring invented a bean with scope of HttpRequest (http://www.tutorialspoint.com/spring/spring_bean_scopes.html). So what happens is that each time you request this bean spring will check if for this specific http request a bean has already been created. If yes you get the reference and if no you will get a new one.
For this to work your application must be a web-aware Spring Application Context. This is so that spring will hook into the http requests and know when to create a new instance.
But what if you want to use this same mechanism but you don’t have a web-aware context? If you did not have spring, the obvious solution would be to store the data you need on the local thread and then you can have access to it from any other class.
So spring actually supports another type of scope that is not in the standard documentation – thread.

Thread Scope

To definite your bean, you will use the standard definition of:
<bean id="sessionData" class="com.company.SessionData" scope="thread"/>

Spring has a class that implements the thread scope which is: SimpleThreadScope. It is a simple implementation with the limitation that it does not support a callback for the destruction of the bean, since it does not know when the thread is finished.
Since this is an unreleased class it is not supported by default and to use it you must register it with spring like any other custom spring bean:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">

    <property name="scopes">

        <map>

            <entry key="thread">

                <bean class="org.springframework.context.support.SimpleThreadScope"/>

            </entry>

        </map>

    </property>

</bean>

.

Summary


When you need to change a lot of code due to API changes, you need to think out of the box and find a solution to magically pass the parameters from one section of the code to another. The solution to this is to isolate the parameters in a spring bean using the proper scope of the bean. You need to read up on spring scopes to find the specific scope that you need. Of course you always have the option to implement your own scope

Monday, January 6, 2014

@Configuration vs xml with prototypes

@Configuration vs xml with prototypes


There are two sides to using spring. One is the injection side, and the annotations are  @Autowire, @Inject, @Resource (see http://javaandroidandrest.blogspot.co.il/2013/05/spring-bean-overriding-between-projects.html). The other side is the definition of beans: @Component, @Repository, @Server.

The beginning of spring all injections were done via xml configuration files. With each version spring added more and more annotations so simplify matters.  When it came to injection annotations were usually used and xml files were used only when the annotation was not enough (like using maps).
For configuration files xml were the main default especially when complex configurations were including. One of the more complicated configurations is the prototype.

Prototypes

Before we go into the @Configuration, I would like to add a word on prototypes. In spring there are two scopes one is singleton and the other prototype. Singleton means that only one instance of that bean will exist in the spring context. While prototype means that multiple beans can exist. If you have a multiple singletons (from different types) that reference a prototype bean, each singleton will get its own instance of the prototype.
For example:
@Component
@Scope("prototype")
public class Chair {

}

@Component
public class Garage {

       @Autowired
       Chair chair;
}

@Component
public class House {

       @Autowired
       Chair chair;

}

Anyone that references the house of the garage will get the same instance as everyone else.  Though in the case of the chair both the garage and the house, will each have a separate instance of the chair.
Now when you need to generate during a runtime of the application another instance of the prototype then you need a lookup method.
For example let’s say that during runtime I need to create a new chair, so on my house class I will have a method of: protected Chair createChair();
We cannot create the chair with new Chair(), since then spring will not generate the class, and any injections within the chair class will not happen. So the spring solution to this is to create a lookup method. In the xml you write:
<bean id="house" class="com.domain.House"
       <lookup-method name="createChair" bean="com.domain.Chair" />
</bean>
And in the class you need to add the abstract method
@Component
abstract public class House {

       @Autowired
       Chair chair;

       abstract protected Chair createChair();
}

Spring will then implement this method and any time you call the createChair() a spring instance of the Chair will all injections will be created.

@ Configuration

With spring 3, spring add the @Configuration annotation. What this annotation allows you to do is to actually write all your xml in java code.
So for creating a bean of House we can either add @Component on the house class, we can add to the xml:
<bean id="house" class="com.domain.House"
      
</bean>
Or we can create a class with the annotation of @Configuration to create the bean:
@Configuration
public class ClassFactory {

       @Bean
       public House createHouse(){
              return new House();
       }
}

So for those people that prefer to write java code over xml files, you can now use configuration classes.
You client code still stays the same and you just inject the House using @Autowired.
Of course since the house is a singleton the method of “createHouse” will be called by spring only once and all places that inject the house will get this instance. In the case of prototypes you will add the method of:
       @Bean
       @Scope("prototype")
       public Chair createChair(){
              return new Chair();
       }

Now anytime that you inject a chair to a bean a new instance of the chair will be instantiated.
The configuration class allows you to set any properties that you want on the bean and write any code that you need. The spring framework will do its magic once the runtime finishes the method with the @Bean annotation. For example the method of “afterPropertiesSet” will be called once the @Bean method finishes.
A added advantage to the configuration bean is now you have a built in lookup method for creating prototype beans. Any class that has the @Configuration annotation is also a spring bean, so you can now inject this bean in your class and call the “createChair”. So you can now write in your house class:
@Component
public class House {

       @Autowired
       Chair chair;
      
       @Autowired
       ClassFactory factory;
      
       public Chair createChair(){
              return factory.createChair();
       }

}




Tuesday, May 21, 2013

Spring bean overriding between projects


Spring bean overriding between projects

Our application is split into two layers. There is the core layer (a layer that is common between multiple projects) and there is the customer/customization layer (layer that is customized per customer). What is needed is to enable the customer layer to override the core dao repository. This means that if in the core there is a dao:
@Repository
public class UserHibernateDao extends GenericHibernateDao<User> implements UserDao {
  public User getUser(){
       return findUniqueByNamedQuery("User.findUserById",id);
  }
}
The customer layer wants to change the getUser method in the core application layer to:
@Repository
public class UserHibernateDaoEx extends UserHibernateDao<User> implements UserDao {
  @Override
  public User getUser(){
       return findUniqueByNamedQuery("User.findUserExById",id);
  }
}
The question is how to override the functionality in spring so that the customer layer bean will be injected into the core classes.
The core classes can use one of the following annotations to inject to UserDao to its classed:
@Autowire, @Resource, @Inject
A summary of the differences between them is as follows (http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/):
@Autowired and @Inject
1.     Matches by Type
2.     Restricts by Qualifiers
3.     Matches by Name

@Resource
1.     Matches by Name
2.     Matches by Type
3.     Restricts by Qualifiers (ignored if match is found by name)

The problem is as follows. Client code is as follows:
@Resource
Private UserDao useDao;
The spring component uses the @Repository annotation for the definition. This annotation is used without a name, so the default name is for the core: userHibernateDao and for the customer: userHibernateDaoEx. When spring tries to inject into userDao using the @Resource, it does not find any component by the name of userDao. Spring then searches by type of UserDao, and finds two implementations and cannot inject the component. By giving the same name to both components spring will complain that there are two components with the same id.
The solution is to use an undocumented feature of spring. You cannot define two components with the same id in the same xml file. But if you can define two beans with the same id in two different xml files, the second bean (depends on the order of the files) will be the one that spring uses.
So in the customer layer, instead of using the @Repository annotation on the inherited dao, it needs to be defined in an xml file.
Summary:
We have found a way for the customer layer to inherit and override a spring bean that has been defined in the core layer in such a way that the new bean definied in the customer layer will be used by the core layer itself and the overridden functionality from the customer layer.


Saturday, March 2, 2013

Spring (3.1) Profiles



We all find ourselves finding solutions to the problem of loading different configurations depending on the environment.
The basic ones are which database to connect to depending if we are in production or testing. 
The options are very large, and the solutions many.

Spring now has the option to add an attribute to each bean with a profile, and then you load the context depending on the profile. This will allow you by one flag to define which beans will be loaded when.

For  more information see this nice blog: