Suggested Pages

Thursday, October 18, 2012

Design Pattern Visitor

In this post I will talk about a not common, but useful design pattern called Visitor.

Before describing it, I'm going to show a simple scenario where I will point up common errors in order to emphasize the importance of knowing design pattern over technologies as JPA, EJB etc..

Let us suppose to have a complex domain where we will consider only three classes: Solid, Cone and Cube. These classes belong to a complex domain and their interface should not be modified.

Remember: A class should have only one responsability and the fewest functions as possible.

Now a new task has to be done: You have an heterogeneous structure composed by Solid instances, and you have to create a simple algorithm that prints Solid of this structure in a "Plain Text" format and in a "XML format"..

Common Bad Solution - 1



A common solution to resolve the above task is to add two methods to the Solid interface: printPlainText and printXML. These methods are implemented by Cone and Cube at their manner. Solution is shown above.

HeterogeneousStructure.java

..

public class HeterogeneousStructure {

 private List structures;

 public List getStructures() {
  return structures;
 }

 public void setStructures(List structures) {
  this.structures = structures;
 }
 
}

Solid.java

...

public interface Solid {

 String printPlainText();

 String printXML();
   
}



Cone.java

..

public class Cone implements Solid {

 private int radius;

 private int height;

 public int getRadius() {
  return radius;
 }

 public void setRadius(int radius) {
  this.radius = radius;
 }

 public int getHeight() {
  return height;
 }

 public void setHeight(int height) {
  this.height = height;
 }

 
 public String printPlainText() {
  return "(cone(radius=" + radius + ", height=" + height + "))";
 }

 
 public String printXML() {
  return " " + radius + ", " + height + " ";
 }

}


Cube.java
...

public class Cube implements Solid {

 private int edge;

 public int getEdge() {
  return edge;
 }

 public void setEdge(int edge) {
  this.edge = edge;
 }
 
 public String printPlainText() {
  return "(cube(edge=" + edge + "))";
 }
 
 public String printXML() {
  return "" + edge + "";
 }
}



Suppose a new task says: Create a new algorithm that prints in a JSON format . To accomplish that task you have to add a new method to the Solid interface.
So you have to modified the bean Solid for each new algorithm and this causes the domain is coupled with external features, as the print feature asked for this task.

Common Bad Solution - 2



We have just said that the problem of the first solution is that if you have to add a different print-algorithm, a new method has to be added to the Solid interface.
Another solution that has to be avoided it's that shown below. The basic idea is to create a class that acts like a Strategy and has two methods: the former to visit Cube object and the latter to visit Cone object.

PrintAlgorithmImpl.java

public class PrintAlgorithmImpl implements PrintAlgorithm {

 private PrintStrategy printStrategy;

 public String print(HeterogeneousStructure structure) {
  String printResult = "";
  List structures = structure.getStructures();
  for (Solid solid : structures) {
   
   if (solid instanceof Cube) {
    printResult+=printStrategy.visit((Cube) solid);
   }
      else if (solid instanceof Cone) {
       printResult+=printStrategy.visit((Cone) solid);
   }
  }
  return printResult;
 }

 public PrintStrategy getPrintStrategy() {
  return printStrategy;
 }

 public void setPrintStrategy(PrintStrategy printStrategy) {
  this.printStrategy = printStrategy;
 }
}


PrintStrategy.java

public interface PrintStrategy {

 public String visit(Cone cone);

 public String visit(Cube cube);
}


PrintStrategyXML.java

public class PrintStrategyXML implements PrintStrategy {


 public String visit(Cone cone){
  return "" + cone.getRadius() + "" + cone.getHeight() + "";
 }
 
 public String visit(Cube cube){
  return "" + cube.getEdge() + "";
 }
}


PrintStrategyPlainText.java
public class PrintStrategyPlainText implements PrintStrategy {

 public String visit(Cone cone){
  return "(cone(radius=" + cone.getRadius() + ", height=" + cone.getHeight() + "))";
 }
 
 public String visit(Cube cube){
  return "(cube(edge=" + cube.getEdge() + "))";
 }

}



Solid.java

public interface Solid {

}


Cone.java


public class Cone implements Solid {

 private int radius;

 private int height;

 public int getRadius() {
  return radius;
 }

 public void setRadius(int radius) {
  this.radius = radius;
 }

 public int getHeight() {
  return height;
 }

 public void setHeight(int height) {
  this.height = height;
 }

}


Cube.java

public class Cube implements Solid {

 

 private int edge;

 public int getEdge() {
  return edge;
 }

 public void setEdge(int edge) {
  this.edge = edge;
 }

  
}

The problem of this solution is that you have to discriminate among the subclasses of Solid interface and invoke the right method of PrintStrategy interface.

Visitor Pattern



The Design Pattern Visitor is a behavioural pattern that suggests to reverse the call: the model object is called passing the strategy object used to visit it and not the inverse.

Problem


Consider to use Visitor Design Pattern when:
  • You have to provide many and different operations over a structure with elements having different interfaces;
  • The structure is immutable but operations can change at runtime;
  • You don't want to modify the element of the structure because of new operations on the structure.

Solution


The solution provided by the Design Pattern Visitor is to classify objects into two categories: Visitor and Visited objects. Visited objects permit visitor objects to visit them in a perfect open/closed principle style: Software entities should be open for extension, but closed for modification. Visited objects permit to change the Visitor (alter its behaviour) but their code doesn't change.

Components


  • Visitor:declares a method called visit(ConcreateElement); for each ConcreateElement of the structures;
  • ConcreteVisitor : the concreate class that implements Visitor interface and has the logic of the new operation;
  • Element: defines a method called accept(Visitor v);
  • ConcreateElement: the concreate class that implements Element interface;
  • ObjectStructure: an aggregation of elements that implement Element interface;

PrintAlgorithmImpl.java


public class PrintAlgorithmImpl implements PrintAlgorithm {

 private PrintVisitor printVisitor;

 public PrintVisitor getPrintVisitor() {
  return printVisitor;
 }

 public void setPrintVisitor(PrintVisitor printVisitor) {
  this.printVisitor = printVisitor;
 }

 public String print(HeterogeneousStructure structure) {
  String printResult = "";
  List structures = structure.getStructures();
  for (Solid solid : structures) {
   printResult += solid.accept(printVisitor);
  }
  return printResult;
 }

}

PrintVisitor.java

public interface PrintVisitor {

 public String visit(Cone cone);
 
 public String visit(Cube cube);
}

PrintStrategyPlainText.java


public class PrintVisitorPlainText implements PrintVisitor{

 
 public String visit(Cone cone){
  return "(cone(radius=" + cone.getRadius() + ", height=" + cone.getHeight() + "))";
 }
 
 public String visit(Cube cube){
  return "(cube(edge=" + cube.getEdge() + "))";
 }
}

PrintStrategyPlainText.java


public class PrintVisitorXML implements PrintVisitor{

 
 public String visit(Cone cone){
  return "" + cone.getRadius() + "" + cone.getHeight() + "";
 }
 
 public String visit(Cube cube){
  return "" + cube.getEdge() + "";
 }
}


Solid.java

public interface Solid {

 public String accept(PrintVisitor printVisitor);
}


Cone.java

public class Cone implements Solid {

 private int radius;

 private int height;

 public int getRadius() {
  return radius;
 }

 public void setRadius(int radius) {
  this.radius = radius;
 }

 public int getHeight() {
  return height;
 }

 public void setHeight(int height) {
  this.height = height;
 }

 
 public String accept(PrintVisitor printVisitor) {
  return printVisitor.visit(this);
 }

}


Cube.java

public class Cube implements Solid {

 

 private int edge;

 public int getEdge() {
  return edge;
 }

 public void setEdge(int edge) {
  this.edge = edge;
 }

 public String accept(PrintVisitor printVisitor) {
  return printVisitor.visit(this);
 }
 
}



Conclusions


In conclusion the power of this design pattern lies in the care with which you use. The strength of Visitor is the use of the technique called double dispatch. This technique consists of using a double polymorphism: in fact the execution of the method element.accept (visitor: Visitor) depends on the couple (ConcreateElement, ConcreateVisitor).

See also:


Monday, October 8, 2012

MVC (Model View Controller)

MVC is an architectural pattern that solves the problem of separating the presentation layer from the model layer. It suggests to distinguish three distinct entities:
  • Model
  • View
  • Controller

Model is the layer of model objects. These objects implement the business logic and they usually are the most reusable objects of your web application.
View is the presentation layer of a web application. View layer is responsible for the receiving of user inputs and for the providing of responses to users.
Controller is the layer responsible of managing the user inputs received by the View layer and of performing actions on the Model Objects. It's an intermediate layer that permits the separation between Model and View. Moreover Controller layer , after performing actions on the Model layer, chooses the view to return to users.
The main Java Frameworks that make use of MVC pattern are: Spring and Struts.

Grasp Pattern

GRASP is an acronim for General Responsibility Assignment Software Pattern. These patterns, as the name suggests, deal with assignment of responsibility.
In my opinion, learn these patterns leads to improve the capability of analysis and programming. The main GRASP design patterns are the followings:
  • Controller
  • Creator
  • High Cohesion
  • Indirection
  • Information Expert
  • Low Coupling
  • Protected Variation
  • Pure Fabrication

Controller

Controller suggests to use an object to intercept system calls. This object represents the entire system for a specific use case, therefore it's the first object called when a client calls the system. It delegates to other objects the responsibility to solve a request.

Creator

Creator solves the problem of assigning the responsibility to create objects in a software system. Given two objects A and B, Creator suggests to use A to create B if:
  • A contains or aggregates instance of B
  • A uses B
  • A has the information to inizialize B

High Cohesion

Hign Cohesion suggests to augment the cohesion inside the same class. This means a good class has methods that satisfy the less number of responsibilities as possible. So a good class has a single specific function and all of its methods, have this goal.

Information Expert

Information Expert solves the problem of assigning a specific responsibility to a class. It suggests to give the responsibility to the class that is the best candidate to perform a responsibility. This class has to have the required information to manage this particular responsibility.

Low Coupling

Low Coupling suggests to reduce dependencies among classes. This leads to limit the impact of changes from a class to another.

Indirection

Indirection solves the problem of avoiding coupling among classes. It suggests to introduce an intermediate object that acts as an adapter between two components that have to be decoupled.

Protected Variation

Protected Variation aims to find points of variation/change in a system and suggests to protect these points so that other software components could not suffer from these changes. Java Interfaces are the best candidate to reach his goal. When a client interacts with a software system, it has to know only the direct interlocutor. An interface permits developers to change real implementation of a software component maintaining the same interface exposed.

Pure Fabrication

Pure Fabrication solves the problem of assigning responsibility when either Expert either HighCohesion either Low Coupling are in conflict to assign this responsibility. Pure Fabrication suggests to put the responsibility into a class that is not a class belonging to the application domain. Now this class can follow High Cohesion e Low Coupling design patterns.

Join Types - Tutorial

The most important join types are:
  • Cross Join
  • Inner Join
  • Outer Join
In this page let's consider the following tables:
  1. Player ( id, firstname , surname , salary ,  team) 
  2. Team  ( id , name , city)

Cross Join

The result of a Cross Join is a carthesian products of all table rows. Examples of cross join are the followings:
  • SELECT * FROM Player CROSS JOIN Team (Explicit Cross Join)
  • SELECT * FROM Player,Team (Implicit Cross Join)
As we can see It's not specified any join predicate for matching.

Inner Join

The inner join compares each row of the Employee table with a row from Department table and verifies if the join predicate is satisfied. If it is satisfied the two table rows are combined in one result row. From another point of view the result of an inner join can be seen as the result of a Cartesian product that is filtered through the join predicate.
Examples of inner join are the followings:
  • SELECT * FROM Player player INNER join Team team ON player.team=team.id (Explicit Inner Join)
  • SELECT * FROM Player player, Team team WHERE player.team=team.id (Implicit Inner Join)

Outer Join

An Outer Join produces a row in the result table even if a matching is not found between two rows compared. It acts as a union of the two tables. You have to distinguish from three types of Outer Join: left,right and full. Examples of outer join are the followings:
  • SELECT * FROM Player player LEFT OUTER JOIN Team team ON player.team = team.id
  • SELECT * FROM Player player RIGHT OUTER JOIN Team team ON player.team = team.id
  • SELECT * FROM Player player FULL OUTER JOIN Team team ON player.team = team.id

Grep Recursive


find . -name \* -exec grep "Search" {} \;


Monday, October 1, 2012

Servlet providing JSON Response

In this post we'll see a simple Servlet that provides an HTTP response in JSON format. To print the response in a JSON format, I'm going to use a library called Jackson.

STEP-1: Adding maven dependencies into your pom.xml


pom.xml
<repositories>
    <repository>
 <id>codehaus-snapshots</id>
 <url>http://snapshots.repository.codehaus.org</url>
    </repository>
</repositories>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.10</version>
</dependency>
   


STEP-2: Create the Servlet


JsonServler.java

package com.simonefolinoblogspot.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;

public class JsonServlet extends HttpServlet{

 private static final long serialVersionUID = 7905177450045184525L;

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  System.out.println("JsonServlet--start");
  System.out.println("requestURI="+req.getRequestURI());
  Items items=new Items();
  List listItems = new LinkedList();
  Item item=new Item();
  item.setValue("val1");
  Item item2=new Item();
  item2.setValue("val2");
  listItems.add(item);
  listItems.add(item2);
  items.setItems(listItems);
  resp.setContentType("application/json");
  PrintWriter out = resp.getWriter();
  ObjectMapper mapper = new ObjectMapper(); 
  mapper.writeValue(out, items);
  System.out.println("JsonServlet--end");
 }
 
}


As you can see I made use of ObjectMapper object that permits to print an application domain object in JSON format.
Items.java

package com.simonefolinoblogspot.servlet;

import java.util.List;

public class Items {
 
 private List<Item> items;

 public List<Item> getItems() {
  return items;
 }

 public void setItems(List<Item> items) {
  this.items = items;
 }

 @Override
 public String toString() {
  return "Items [items=" + items + "]";
 }
 
}

Item.java

package com.simonefolinoblogspot.servlet;

public class Item {

 private String value;

 public String getValue() {
  return value;
 }

 public void setValue(String value) {
  this.value = value;
 }

 @Override
 public String toString() {
  return "Item [value=" + value + "]";
 }
}

When the Servlet is invoked the response is in JSON format and is something like this:
Response

{"items":[{"value":"val1"},{"value":"val2"}]}


Saturday, September 29, 2012

Create and Install a Custom Maven Archetype - Tutorial

In this post I will show how to create a simple maven archetype.

Create Maven Archetype


You have to create a folder tree as this shown below:


STEP-1: Create a folder for the configuration files


As you can see in the previuos snapshot, you have to create a folder /META-INF/maven to put both archetype.xml and archetype-metadata.xml.

STEP-2: Create archetype.xml into folder /META-INF/maven/archetype.xml


In this file you should register all the resources of your archetype and distinguish among resources, sources, etc..
archetype.xml
<?xml version="1.0" encoding="UTF-8"?>
<archetype>
 <id>${artifactId}</id>
 <sources>
     <source>src/main/java/com/simonefolinoblogspot/mavenarchetype/main/Sample.java</source>
   </sources>
 <resources>
  <resource>src/main/webapp/resources/css/main.css</resource>
  <resource>src/main/webapp/resources/js/main.js</resource>
  <resource>src/main/webapp/WEB-INF/web.xml</resource>
  <resource>src/main/webapp/jsp/index.jsp</resource>
 </resources>
</archetype>
   

STEP-3: Create archetype-metadata.xml into folder /META-INF/maven/archetype-metadata.xml


archetype-metadata.xml

<?xml version="1.0" encoding="UTF-8"?>

<archetype-descriptor name="simple-webapp-archetype">
 <fileSets>
  <fileSet encoding="UTF-8" filtered="true">
   <directory>src/main/java</directory>
  </fileSet>
  <fileSet encoding="UTF-8" filtered="true">
   <directory>src/main/resources</directory>
  </fileSet>
  <fileSet encoding="UTF-8" filtered="true">
   <directory>src/main/webapp</directory>
  </fileSet>
 </fileSets>
</archetype-descriptor>


STEP-4: Create a pom.xml into the root of your maven archetype


In the following snippet of code you can notice that groupId, artifactId and versionId are parametrized.
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>${groupId}</groupId>
 <artifactId>${artifactId}</artifactId>
 <name>${artifactId}</name>
 <version>${version}</version>
 <packaging>jar</packaging>
 <build>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
     <encoding>UTF-8</encoding>
     <source>1.5</source>
     <target>1.5</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
 <dependencies>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.4</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>jsp-api</artifactId>
   <version>2.0</version>
   <scope>provided</scope>
  </dependency>
 </dependencies>
</project>


STEP-5: Create the structure of your custom archetype into the folder <CUSTOM-MAVEN-ARCHETYPE>/src/main/resources/archetype-resources/


Under the folder archetype-resources you have to put the structure declared in the configuration files written in the previous steps. This folder is the container of your project's archetype.

Install Maven Archetype


Open the shell and go to the path <CUSTOM-MAVEN-ARCHETYPE> at the same level of the first pom.xml in the folder tree. Then you type the following instruction:

mvn clean 
    install 
        -DartifactId=archetypeArtifactId 
        -DgroupId=archetypeGroupId 
        -Dversion=1.0-snapshot 
    archetype:update-local-catalog 
    archetype:crawl


Generate project from Archetype


Open the shell and type the following instruction at the path you prefer.


mvn archetype:generate 
    -DinteractiveMode=false  
    -DarchetypeArtifactId=archetypeArtifactId   
    -DarchetypeGroupId=archetypeGroupId   
    -DarchetypeVersion=1.0-snapshot      
    -DgroupId=mygroup
    -DartifactId=myartifactId
    -Dversion=1.0-snapshot
    -DarchetypeRepository=/repository 
    -DarchetypeCatalog=local



Suggested Posts:


HTML Response and Content Types

HTTP Response and data stream


The HTTP protocol has two main phases of communication:
  • HTTP REQUEST;
  • HTTP RESPONSE.
The HTTP response is a single data stream, so when you ask for a web page containing images, embedded in the stream there are links to resources (as images) that need additional requests. The browser has the responsibility to make these requests.

Content-Type


An HTTP response has got many HTTP headers. One of these is called Content-Type. It specifies what type of file that has been sent by the server and it's used by the browser to process the data stream.
Here are the most common content types:
  • text/html: HTML;
  • application/octet-stream:Arbitrary binary data;
  • application/zip: ZIP archive files;
  • image/jpeg: Images files;


Is it possible to make an HTTP response with different content types?


If you want to send different files you should use a ZIP file.


Suggested Posts:

Encryption, Hashing and Session

You should not store passwords in clear in Session. Generally it's recommended to store hash password to avoid the reverse engineering.

Hashing


Registration


A common practice is to store hash password in databases and never store passwords as plain text anywhere in your application. During a registration , you provide a plain password that is used at this way:
  • A salt is added to to the plain password;
  • The new string (plain password salt) is used to generate an hash value with SHA-1 or MD5 algorithm;
  • The hash value is stored in DB.

Authentication


Authentication is a similar process of that described above. The plain password provided in the login formis used at this way:
  • A salt is added to to the plain password;
  • The new string ( plain password salt ) is used to generate an hash value with SHA-1 or MD5 algorithm;
  • The hash value is compared with the hash value stored in DB and retrieved by username.


Encryption

Encryption is different from hashing because you can decrypt the encrypted text to get the original text, instead hashing does not permit to obtain the original text from the hash value

Suggested Posts:

Friday, September 28, 2012

JPA Bidirectional Association

In this post we'll see an example of a bidirectional OneToMany-ManyToOne relationship in JPA.
A common example of OneToMany-ManyToOne relationship is Parent-Child relationship.

Object Point of View



Child.java

...

@Entity
public class Child {
 
 @Id
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne
 private Parent parent;

...

}

Parent.java

...
@Entity
public class Parent {
 
 @Id
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(mappedBy="parent")
 private List children;
        
 ...
}


Database Point of View

create table Child (
        childId integer not null,
        name varchar(255),
        parent_parentId integer,
        primary key (childId)
)

create table Parent (
        parentId integer not null,
        name varchar(255),
        primary key (parentId)
)

alter table Child 
        add constraint FK3E104FC9E7EF479 
        foreign key (parent_parentId) 
        references Parent


As you can see, if you don't tell JPA to use a Join Table explicitly only two tables are created: the Child table that has a foreign key to Parent table .

JPA Set vs List

In this post we'll see the difference on the using of Set and List in a unidirectional association.

List and @JoinTable


Object Point of View

@Entity
public class Parent {
 
@Id
private int parentId;
 
@Column
private String name;

@OneToMany
@JoinTable(name="Parent_Child", joinColumns=@JoinColumn(name="parentId"), inverseJoinColumns=@JoinColumn(name="childId"))
private List<Child> children;

 ...

}


Database Point of View

create table Parent_Child (
        parentId integer not null,
        childId integer not null,
        unique (childId)
)

create table Child (
        childId integer not null auto_increment,
        name varchar(255),
        primary key (childId)
)

create table Parent (
        parentId integer not null auto_increment,
        name varchar(255),
        primary key (parentId)
)

alter table Parent_Child 
        add index FK5AF11D47C916AC84 (parentId), 
        add constraint FK5AF11D47C916AC84 
        foreign key (parentId) 
        references Parent (parentId)

alter table Parent_Child 
        add index FK5AF11D47ABE0291E (childId), 
        add constraint FK5AF11D47ABE0291E 
        foreign key (childId) 
        references Child (childId)



Set and @JoinTable


Object Point of View


@Entity
public class Parent {

@Id
private int parentId;

@Column
private String name;

@OneToMany
@JoinTable(name="Parent_Child", joinColumns=@JoinColumn(name="parentId"), inverseJoinColumns=@JoinColumn(name="childId"))
private Set<Child> children;


...
}


Database Point of View

create table Parent_Child (
        parentId integer not null,
        childId integer not null,
        primary key (parentId, childId),
        unique (childId)
)


create table Child (
        childId integer not null auto_increment,
        name varchar(255),
        primary key (childId)
)


create table Parent (
        parentId integer not null auto_increment,
        name varchar(255),
        primary key (parentId)
)


alter table Parent_Child 
        add index FK5AF11D47C916AC84 (parentId), 
        add constraint FK5AF11D47C916AC84 
        foreign key (parentId) 
        references Parent (parentId)

alter table Parent_Child 
        add index FK5AF11D47ABE0291E (childId), 
        add constraint FK5AF11D47ABE0291E 
        foreign key (childId) 
        references Child (childId)


As you can see the join table Parent_Child has both a primary key both a unique constraint.

So the most important difference is that the conversion into database scripts, preserves the concept of uniqueness of Child entity into the collection associated to a specific Parent.

You cannot associate the same Child object to the same Parent object, as you cannot insert into database two entries with the same couple (Child,Parent) into Parent_Child table.

Thursday, September 27, 2012

Forward, Include and Redirect

In this post we'll see the differences among the techniques of forward, include and redirect .

Forward


The method forward of RequestDispatcher, allows the server to literally forward the request to another resource (same server or same domain) maintaining all request's parameters. It's usually used when you want the request to be served by another resource (Servlet or JSP) in place of the calling Servlet.

Include


The method include of RequestDispatcher, allows the server to include the contents of the specified resource in the flow of the servlet response. The included resource cannot change:
  • The response status code;
  • The HTTP headers.
Any attempt to modify headers is ignored.

Redirect


The method sendRedirect of HttpServletResponse, tells to the client that it has to send a new request to the pointed path. Therefore it causes two requests to the server from the client. It's used generally to redirect towards other servers and domains.

Example


In the following snippets of code, you have a complete example of how forward, include and redirect work. You can notice that:
  • If you click the anchor Forward, HiServlet forwards to hi.jsp and the printed output is:
    hi=good morning method=forward

  • If you click the anchor Incluce, HiServlet includes hi.jsp and the printed output is:
    hi=good morning method=forward

  • If you click the anchor Redirect, HiServlet tells the client to do another request to the URL http://<host>/hiServlet/jsp/hi.jsp. The printed output is:
    hi=null method=null

  • If you click the anchor Forward & ChangeHeader, HiServlet forwards to hi.jsp and the header Content-Type is set to application/octet-stream:

  • If you click the anchor Include & ChangeHeader, HiServlet includes hi.jsp and the header Content-Type is not set to application/octet-stream

  • If you click the anchor Redirect & ChangeHeader, HiServlet redirects to hi.jsp and the header Content-Type is not set to application/octet-stream
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>hiServlet</display-name>
 
 <servlet>
  <servlet-name>hiServlet</servlet-name>
  <servlet-class>com.simonefolinoblogspot.servlet.HiServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>hiServlet</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
 
 <welcome-file-list>
  <welcome-file>/jsp/index.jsp</welcome-file>
 </welcome-file-list>

</web-app>

HiServlet

...

public class HiServlet extends HttpServlet {

 private static final long serialVersionUID = 6167525405783177839L;

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
   throws ServletException, IOException {
  
  System.out.println("doGet()--start");
  
  String method = req.getParameter("method"); 
 
  System.out.println("method="+method);
  
  req.setAttribute("hi", "good morning");
  
        if(method.equals("forward")){
         RequestDispatcher requestDispatcher = req.getRequestDispatcher("/jsp/hi.jsp"); 
         requestDispatcher.forward(req, resp);
        
        }else if(method.equals("include")){
         RequestDispatcher requestDispatcher = req.getRequestDispatcher("/jsp/hi.jsp");
         requestDispatcher.include(req, resp);
         
        }
        else if (method.equals("redirect")){
         resp.sendRedirect("/hiServlet/jsp/hi.jsp");         
        }
        else{
         resp.sendError(500);
        }
        System.out.println(req.getHeader("Content-Type"));
        System.out.println("doGet()--end");
 }

}

index.jsp
<html>
<head>
<title>EncodePageExample</title>
</head>

<body>
 <ul>
  <li><a href="/hiServlet/hi.do?method=forward">Forward</a></li>
  <li><a href="/hiServlet/hi.do?method=include">Include</a></li>
  <li><a href="/hiServlet/hi.do?method=redirect">Redirect</a></li>
  
  <li><a href="/hiServlet/hi.do?method=forward&changeContentType=application/octet-stream">Forward & ChangeHeader</a></li>
  <li><a href="/hiServlet/hi.do?method=include&changeContentType=application/octet-stream">Include & ChangeHeader</a></li>
  <li><a href="/hiServlet/hi.do?method=redirect&changeContentType=application/octet-stream">Redirect & ChangeHeader</a></li>
  
  
 </ul>
</body>

</html>
hi.jsp

<html>
<head>
 <title>DispatcherExample</title>
</head>

<body>

 <%
  String hi=(String)request.getAttribute("hi");
  String method=(String)request.getParameter("method");
  out.println("hi="+hi);
  out.println("method="+method);
  String changeContentType=(String) request.getParameter("changeContentType");
  if(changeContentType!=null){
    response.setHeader("Content-Type", changeContentType);
  }
 %>
 
</body>

</html>

Monday, September 24, 2012

SessionCookie vs URL Rewriting

In this post I will write about HTTP Session in a Web Application. There are a few ways to design session:
  • Store session ID in cookie file
  • Store session ID in the URL

Session Cookie


HTTP Session can be considered as a server area to store information that have to be shared over multiple HTTP requests.
The server uses the session identifier sent by the client to identify the session which the client belongs to. The server reads that ID in order to refer to the session data used by that client.
Generally the session identifier is on the client browser and it's sent to the server, but when the browser windows are closed, the browser deletes the session identifier.
Session IDs are usually stored in a cookie called Session cookie
Session ID is assigned when a new Session is created. Generally this happened:
  • When it's the first time access to the server;
  • When the browser is closed and the cookie is deleted;
  • When the server terminates a session after a few minutes of inactivity.



URL Rewriting

URL Rewriting is a mechanism that allows the server to associate an HTTP request to a stored session on the server when a client disables cookie storing.
Server uses the ID send with the URL to track sessions. For example an URL like this:
   <a href="/add/link">ADD LINK</a>
is rewritten into
    <a href="/add/link;jsessionid=DA22145SSGE2">ADD LINK</a>
The web server extracts jsessionid from the URL to obtain the reference to the HttpSession. To produce this translaction you can use encodeURL() and encodeRedirectURL()

Let's suppose to have a servlet EncodeUrlServlet.
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>encodeurl</display-name>
 
 <servlet>
  <servlet-name>encodeUrlServlet</servlet-name>
  <servlet-class>com.simonefolinoblogspot.servlet.EncodeUrlServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>encodeUrlServlet</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
 
</web-app>

EncodeUrlServlet.java

package com.simonefolinoblogspot.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class EncodeUrlServlet extends HttpServlet{

 private static final long serialVersionUID = 6167525405783177839L;

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
   throws ServletException, IOException {
  
  
  // if no session is found, a new one is created
  HttpSession session = req.getSession(true);
  
  System.out.println("session id="+session.getId());
  
  String actionURL="/session-encodeurl/encode.do";
  
  req.setAttribute("actionURL",resp.encodeURL(actionURL));
  
  req.getRequestDispatcher("/jsp/encode.jsp").forward(req, resp);
  
 }
  
}

encode.jsp

<html>
<head>
 <title>EncodePageExample</title>
</head>

<body>

 <a href="<%=request.getAttribute("actionURL")%>">Call Again </a>
 
</body>

</html>

If you disable the cookies on your browser and ask for http://<hostname>/<context>/encode.do you are forwarded to encode.jsp that prints the HTML written below.
encode.jsp

<html>
<head>
 <title>EncodePageExample</title>
</head>

<body>

 <a href="/session-encodeurl/encode.do;jsessionid=820F618F79E21B5E541CE129C0E0EFE5">Call Again </a>
 
</body>

</html>

Tuesday, September 11, 2012

Hibernate Session vs SessionFactory

In Hibernate there are two important classes to know:

Session is not thread safe


Session it is not implemented to be thread safe.
In a multi-thread environment each thread/transaction should obtain its own instance of Session from a SessionFactory.
See Session API.

SessionFactory is thread safe


SessionFactory is immutable. Once the session has created its state it's set for all the life time.
See Session Factory API.

Immutable Objects


For more information about Immutable Object see Immutable Object

Cannot create TypedQuery for query with more than one return - Problem

In this post it's shown a common problem when using a typed query in JPA.

Problem


NamedQuery


@NamedQuery(name = "User.findUserByUsername", query = "SELECT u,p FROM User u JOIN u.profile p WHERE u.username=:username"),


Stacktrace

java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return
 at org.hibernate.ejb.AbstractEntityManagerImpl.createNamedQuery(AbstractEntityManagerImpl.java:506)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)



Solution


Replace this:
 
   entityManager.createNamedQuery("User.findUserByUsername",User.class);

with

  entityManager.createNamedQuery("User.findUserByUsername");

Web Service with Apache CXF - Tutorial


In this post we'll see an example of a Web Service with Apache CXF using Maven.

Step 1: Declare Maven dependencies in your pom.xml


pom.xml

 <!-- apache cxf  --> 
 <dependency>
     <groupId>org.apache.cxf</groupId>
     <artifactId>cxf-rt-frontend-jaxws</artifactId>
     <version>${cxf.version}</version>
 </dependency>
 <dependency>
     <groupId>org.apache.cxf</groupId>
     <artifactId>cxf-rt-transports-http</artifactId>
      <version>${cxf.version}</version>
 </dependency>

 <!-- spring --> 
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>${spring.version}</version>
 </dependency>
 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context-support</artifactId>
     <version>${spring.version}</version>
 </dependency>
 <dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${spring.version}</version>
 </dependency>


Step 2: Add CXFServlet into the web.xml of your Web application



<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <display-name>apachecxfwsexample1</display-name>


 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <!-- middleware configuration -->
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:META-INF/spring/spring-*.xml</param-value>
 </context-param>

 <!-- Apache CXF Servlet -->
 <servlet>
     <servlet-name>CXFServlet</servlet-name>
     <servlet-class>
         org.apache.cxf.transport.servlet.CXFServlet
     </servlet-class>
   </servlet>
 
 <servlet-mapping>
      <servlet-name>CXFServlet</servlet-name>
      <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>


Step 3: Create the Web Service


First write the SEI (Service Endpoint Interface) HelloService annotated with @WebService, then the class HelloServiceImpl that implements the interface.

HelloService.java
package com.simonefolinoblogspot.apachecxf.ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * 
 * 
 * Service Endpoint Interface (SEI)
 *
 */
@WebService
public interface HelloService {
 
 @WebMethod(operationName="sayHello")
 public String sayHello(@WebParam(name="name")String name);

}


HelloServiceImpl.java

package com.simonefolinoblogspot.apachecxf.ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;


@WebService(endpointInterface="com.simonefolinoblogspot.apachecxf.ws.HelloService",serviceName = "HelloService")
public class HelloServiceImpl implements HelloService{

 
 @WebMethod(operationName="sayHello")
 public String sayHello(@WebParam(name="name")String name) {
  return "hi "+name+" !";
 }

}

Step 4: Create the configuration file cxf-servlet.xml


In the file web.xml it's declared cxf-servlet.xml as the file to put the configurations of web services.
cxf-servlet.xml


<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd
 http://cxf.apache.org/jaxws
 http://cxf.apache.org/schemas/jaxws.xsd">
 
 <!-- START needed to import apache cxf configuration START -->
 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
 <!-- END needed to import apache cxf configuration  END-->

 <!-- the service is available at http://<hostname>/<context>/helloservice -->

 <jaxws:endpoint id="helloservice"
  implementor="com.simonefolinoblogspot.apachecxf.ws.HelloServiceImpl"
  address="/helloservice" />
</beans>


Step 5: Write a Client to test the web service




package com.simonefolinoblogspot.apachecxf.ws.client;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;

import com.simonefolinoblogspot.apachecxf.ws.HelloService;

public final class Client {

    private static final QName SERVICE_NAME  = new QName("http://ws.apachecxf.simonefolinoblogspot.com/", "HelloService");
    private static final QName PORT_NAME = new QName("http://ws.apachecxf.simonefolinoblogspot.com/", "HelloServicePort");


    private Client() {
    } 

    public static void main(String args[]) throws Exception {
        Service service = Service.create(SERVICE_NAME);
        // Endpoint Address
        String endpointAddress = "http://localhost:8083/apachecxfwsexample1/helloservice";

        // Add a port to the Service
        service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
        
        HelloService hw = service.getPort(HelloService.class);
        System.out.println(hw.sayHello("Simone"));

    }

}

Sunday, September 2, 2012

Stateful Session Bean Clustered - Tutorial

In this post I'll show an example of a Stateful Sesson Bean Clustered that implements a simple counter.
In a few steps we'll see how to configure a load balancer with Apache HTTP Server using Session Affinity on two JBoss nodes. Then we'll see the behaviour of the implemented Session Bean after a simulated failover: when one of the JBoss nodes fails, the Session will be replicated on the other active JBoss node.

Step-1: Configure Apache HTTP Server


First we have to configure the files <APACHE-HOME>/conf/workers.properties and <APACHE-HOME>/conf/httpd-vhosts.conf.
conf/workers.properties

=\
# Define list of workers that will be used
# for mapping requests
worker.list=loadbalancer,status

# Define Node1
# modify the host as your host IP or DNS name.
worker.node1.port=8009
worker.node1.host=node1.counter.cluster.com
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.cachesize=10

# Define Node2
# modify the host as your host IP or DNS name.
worker.node2.port=8009
worker.node2.host= node2.counter.cluster.com
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.cachesize=10

# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1
#worker.list=loadbalancer

# Status worker for managing load balancer
worker.status.type=status
httpd-vhosts.conf


<VirtualHost *:80>
  DocumentRoot “/local/docroot/htdocs”
  Include conf/tuo.conf
  JkMount /cluster/* loadbalancer
  ...
</VirtualHost>



Step-2: Startup of the JBoss nodes


We have to startup the two JBoss instances that are on the same subnet (to make it simple).

Startup of JBoss node on address 10.3.0.110


./run.sh -c  all  -b  10.3.0.110 -Djboss.messaging.ServerPeerID=1


Startup of JBoss node on address 10.3.0.109


./run.sh -c  all  -b  10.3.0.109 -Djboss.messaging.ServerPeerID=2


Wait the two nodes start communicating each other


11:52:10,764 INFO  [DefaultPartition] New cluster view for partition DefaultPartition (id: 1, delta: 1) : [10.3.0.110:1099, 10.3.0.109:1099]
11:52:10,766 INFO  [DefaultPartition] I am (10.3.0.110:1099) received membershipChanged event:
11:52:10,767 INFO  [DefaultPartition] Dead members: 0 ([])
11:52:10,767 INFO  [DefaultPartition] New Members : 1 ([10.3.0.109:1099])
11:52:10,767 INFO  [DefaultPartition] All Members : 2 ([10.3.0.110:1099, 10.3.0.109:1099])
11:52:10,890 INFO  [RPCManagerImpl] Received new cluster view: [10.3.0.110:53063|1] [10.3.0.110:53063, 10.3.0.109:1102]
11:52:22,027 INFO  [GroupMember] org.jboss.messaging.core.impl.postoffice.GroupMember$ControlMembershipListener@4d16c81d got new view [10.3.0.110:53063|1] [10.3.0.110:53063, 10.3.0.109:1102], old view is [10.3.0.110:53063|0] [10.3.0.110:53063]
11:52:22,028 INFO  [GroupMember] I am (10.3.0.110:53063)
11:52:22,028 INFO  [GroupMember] New Members : 1 ([10.3.0.109:1102])
11:52:22,028 INFO  [GroupMember] All Members : 2 ([10.3.0.110:53063, 10.3.0.109:1102])

As you can see the two instances has found each other and communicates with JGroup protocol. Afterwards this communication the cluster consists of two instances: Received new cluster view: [10.3.0.110:53063|1] [10.3.0.110:53063,10.3.0.109:1102].

Step-3: Write the Statefull Session Bean Clustered


We have to write a simple Session Stateful Bean that uses an instance variable called count. This counter is incremented on each call to the enterprise method.

CounterServiceRemote.java
...

import javax.ejb.Remote;

@Remote
public interface CounterServiceRemote {
 public void increase();
}


CounterService.java
....

import javax.ejb.Stateful;

import org.jboss.ejb3.annotation.Clustered;

/**
 * Session Bean implementation class CounterService
 */
@Stateful
@Clustered
public class CounterService implements CounterServiceRemote{

    private int count=0;
    
    public CounterService() {
       
    }
    public void increase(){
     System.out.println("counter:"+count);
     count++;
     System.out.println("counter:"+count);
    }

}



Step-4: Deploy the jar containing the EJB in both the JBoss nodes


You have to put the jar into the directory <JBOSS-NODE>/server/all/deploy.

Step-5: Wait the deploy to be completed


Console Output

12:33:50,115 INFO  [JndiSessionRegistrarBase] Binding the following Entries in G
lobal JNDI:

        CounterService/remote - EJB3.x Default Remote Business Interface
        CounterService/remote-com.clusterproject.CounterServiceRemote - EJB3.x R
emote Business Interface

12:33:50,205 INFO  [PlatformMBeanServerRegistration] JBossCache MBeans were succ
essfully registered to the platform mbean server.
12:33:50,225 INFO  [STDOUT]


Step-6: Verify in the JMX console that the Stateful Session Bean is registered



Step-7: Verify in the JMX console that the cluster is online



Step-8: Run the EJB client


ClientEJB.java

....

import javax.naming.NamingException;
import com.clusterproject.CounterServiceRemote;

public class ClientEJB {

   public static void main(String[] args) {
 try {
  Object obj =           
ServiceLocator.getInitialContext().lookup("CounterService/remote");
  CounterServiceRemote counterServiceRemote =(CounterServiceRemote) obj;
  counterServiceRemote.incrementa();
  Thread.sleep(10000);
  counterServiceRemote.incrementa();
  Thread.sleep(10000);
  counterServiceRemote.incrementa();
 } catch (NamingException e) {
  e.printStackTrace();
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
  } 
}


ServiceLocator.java
....

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ServiceLocator {

 public static Context getInitialContext(){
  Properties properties =new Properties();
  properties.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
  properties.put(Context.PROVIDER_URL, "jnp://counter.cluster.com:1099");
  InitialContext jndiContext=null;
  try {
   jndiContext=new InitialContext(properties);
  } catch (NamingException e) {
   e.printStackTrace();
  }
  return jndiContext;
 }
}

It's important to notice that:
  • The instruction Thread.sleep(10000) is useful to wait the simulated fault of JBoss node;
  • The address counter.cluster.com is the jnp address of the load balancer machine. The EJB client has to know the address of the balancer machine.
After running the EJB client the below message will be written by the JBoss node that will serve the request.

INFO  [STDOUT] counter:0
INFO  [STDOUT] counter:1



Step-9:Shutdown of the serving JBoss node


During the waiting caused by Thread.sleep(10000), we have to shutdown the serving JBoss node. In this example I have used the JBoss instance on 10.3.0.110.

After the shutdown completes, the active JBoss node will continue serving the request. As you can see in the following console lines:
  • Dead members: 1 ([10.3.0.110:35429])
  • All Members : 1 ([10.3.0.109:1148])

Output

12:38:36,377 INFO  [RPCManagerImpl] Received new cluster view: [10.3.0.110:35429 |6] [10.3.0.109:1148]
12:38:36,577 INFO  [GroupMember] org.jboss.messaging.core.impl.postoffice.GroupM
ember$ControlMembershipListener@191a87d got new view [10.3.0.109:1148|10] [10.3.0.109:1148], old view is [10.3.0.109:1148|9] [10.3.0.109:1148, 10.3.0.110:35429]
12:38:36,577 INFO  [GroupMember] I am (10.3.0.109:1148)
12:38:36,587 INFO  [GroupMember] Dead members: 1 ([10.3.0.110:35429])
12:38:36,587 INFO  [GroupMember] All Members : 1 ([10.3.0.109:1148])
12:38:37,779 INFO  [RPCManagerImpl] Received new cluster view: [10.3.0.109:1148|
10] [10.3.0.109:1148]
12:38:37,849 INFO  [DefaultPartition] New cluster view for partition DefaultPart
ition (id: 10, delta: -1) : [10.3.0.109:1099]
12:38:37,849 INFO  [DefaultPartition] I am (10.3.0.109:1099) received membership
Changed event:
12:38:37,849 INFO  [DefaultPartition] Dead members: 1 ([10.3.0.110:1099])
12:38:37,849 INFO  [DefaultPartition] New Members : 0 ([])
12:38:37,859 INFO  [DefaultPartition] All Members : 1 ([10.3.0.109:1099])
12:38:39,211 INFO  [STDOUT] counter:1
12:38:39,211 INFO  [STDOUT] counter:2
12:38:49,245 INFO  [STDOUT] counter:2
12:38:49,245 INFO  [STDOUT] counter:3



In summary this is only a simple rough example of a Clustered Session Bean, but I hope this post has arouse your curiosity about this subject.

Saturday, August 4, 2012

Sticky Sessions

Sticky Sessions or Session Affinity

Sticky Sessions or Session Affinity means that incoming requests with the same session are routed to the same Tomcat worker.

Load Balancer

A load-balancer tracks HTTP requests and it dispatches the request to the appropriate node.

Load Balancer and Session Replication

Using a load balancer with session affinity, when a session is created on a node of the cluster, every future request will be sent and served by the same node.
Session replication is solved at this way: each request for a session will be handled by the same node. If the node dies, the session will be lost and the client has to login again into the system and starts a new session. Actually with load balancer and session affinity, you cannot replicate HTTP session.

modjk and sticky session

In the following snippet of code you can see an example of workers.properties to be configured on conf dir of Apache HTTP.

conf/workers.properties
# Define list of workers that will be used
# for mapping requests
worker.list=loadbalancer,status

# Define Node1
# modify the host as your host IP or DNS name.
worker.node1.port=8009
worker.node1.host=node1.mydomain.com 
worker.node1.type=ajp13
worker.node1.lbfactor=1
worker.node1.cachesize=10

# Define Node2
# modify the host as your host IP or DNS name.
worker.node2.port=8009
worker.node2.host=node2.mydomain.com
worker.node2.type=ajp13
worker.node2.lbfactor=1
worker.node2.cachesize=10

# Load-balancing behaviour
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1


# Status worker for managing load balancer
worker.status.type=status

Thursday, August 2, 2012

Transaction Isolation Level and Anomalies

Conflict Transactions


Two concurrent transactions T1 and T2 are in conflict if they perform an action on the same object. There are three possible conflicts:
  • (WR) Write-Read: t1 reads an object that was previously written by t2;
  • (RW) Read-Write: t2 writes an object that was previously read by t1;
  • (WW) Write-Write: t2 writes an object that was previously written by t1

Anomalies

Consider the following table:
Employee
id
name
age
salary


Lost Update (WW)

We can distinguish two kinds of lost update.
  • First type: two transactions update rows using a single UPDATE statement and do not base the update on the previously retrieved values; It may occur when a transaction t1 can write a value of an object written by another transaction t2 not yet completed. The transaction t1 overwrites the update made by T2.
  • Second Type: two transactions each retrieve the same row, and then later update the row based on the originally retrieved values.
The first type can be resolved by the Read Uncommitted isolation level, instead the second type can be resolved only at Repeatable Read.

Dirty Read (WR)

It may occur when a transaction t1 can read a value modified by another transaction t2 not yet completed. T1 reads an intermediate value because t2 should rollback.

    TRANSACTION1 (t1)             TRANSACTION2 (t2)


    SELECT emp.salary 
    FROM employee
    WHERE id = 100;
                                  UPDATE users emp 
                                  SET emp.salary = 5000 
                                  WHERE id = 1;
    /*intermediate read value*/ 
    SELECT emp.salary 
    FROM employee
    WHERE id = 100;
                                  ROLLBACK;



Unrepeatable Read (RW)

It may occur when a transaction t2 can write a value of an object read by another transaction t1 not yet completed. So the transaction t1 reads different values ​​for the same data at different times.


     TRANSACTION1 (t1)             TRANSACTION2 (t2)

    /* first read*/
    SELECT emp.salary 
    FROM employee
    WHERE id = 100;
                                  UPDATE users emp 
                                  SET emp.salary = 5000 
                                  WHERE id = 1;
                                  COMMIT;
    /* second read*/
    SELECT emp.salary 
    FROM employee
    WHERE id = 100;
    COMMIT;
 

Phantom Read

It may occur when a set or of tuples,read by a transaction t2, are changed by t1. It usually occurs when a transaction t1 that performs a SELECT with a WHERE clause reads a set of tuples and another transaction t2 adds tuples in that set. This anomaly can be consider a special unrepeatable read where a lock on a set of tuples has not been acquired.

       TRANSACTION1                     TRANSACTION2

      
      SELECT * FROM Employee
      WHERE salary<1000 and salary>500;


                                        INSERT INTO Employee VALUES ( 100, 'Simone', 27 ,800);                               COMMIT;


      SELECT * FROM Employee
      WHERE salary<1000 and salary>500;




Isolation Level



Read Uncommitted

This isolation level avoids lost update (first type described in the anomalies section above). A transaction t1 can't override changes made by another transaction. In this isolation level a transaction can read data that will be rollbacked (uncommitted) because read locks are not managed.
At this isolation level, if you perform a SELECT query, you don't need any lock to acquire.

Read Committed

This isolation level avoids dirty read and lost update (first type described in the anomalies section above). A write lock (exclusive lock) can't be released until the end of the transaction, instead a read lock (shared lock) can be released after a read is performed. No range-locks is managed in this isolation level.
At this isolation level before reading a row, a transaction must check if another transaction has a write lock. It cannot read any write-locked rows and so it must wait the write lock to be released.

Repeatable reads

This isolation level avoids unrepeatable read, dirty read and lost update(first type and second type described in the anomalies section above) . Both write lock and read lock are exclusive locks and they are released only at the end of the transaction. No range-locks is managed in this isolation level.
At this isolation level to avoid unrepeatable read, a transaction that has to read an object, acquires a read lock and holds it until the transaction completes.

Serializable

This isolation level avoids all anomalies. Both write lock and read lock are exclusive locks. Besides range locks are managed in this level. So when you make a SELECT with a WHERE clause, a range-locks must be acquired.

Shared Lock vs Exclusive Lock


Shared Lock

Shared Locks are released after the read or write operation completes.

Exclusive Lock

Exclusive Locks are released only at the end of the transaction.

Tuesday, July 31, 2012

Transaction Commit and Transaction Rollback

A transaction has only two ways to end: commit or rollback. If you don't commit or rolls back explicitly, the transaction remains alive and it may holds locks (exclusive lock).
Then when the connection is closed by the client, the transaction will commit or roll back depending on how the vendor implements the JDBC specification that doen't say nothing about it.
For example Oracle driver commits on closed connection.

JPA Persistence context as First Level Cache


The Persistence Context is a set of entities in the Managed State. Entities in Persistence Context have a unique persistent identity and these entities are used to synchronize objects in memory with objects in the database.
In this post we'll see how the Persistence Context acts like a first level cache.

Code Example


GenericDAO.java
....

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest",type=PersistenceContextType.TRANSACTION)
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void saveRequired(Child child) {
  entityManager.persist(child);
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public Child findByIdRequired(int childId) {
  return entityManager.find(Child.class, childId);
 }

 @Transactional(propagation = Propagation.REQUIRED)
 public Child saveAndFindRequired(Child child) {
  entityManager.persist(child);   
  return entityManager.find(Child.class, child.getChildId());
 }
 
}


DAOTest.java
...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;

 @Test
 public void testSaveDifferentPersistentContext() {
  System.out.println("------------testSaveDifferentPersistentContext(): start -------");
  Child child = new Child();
  child.setName("child");
  child.setChildId(1);
  genericDAO.saveRequired(child);
  Child findById = genericDAO.findByIdRequired(child.getChildId());
  System.out.println(findById);
  System.out.println("------------testSaveDifferentPersistentContext(): end -------");
 }
 
 @Test
 public void testSaveSamePersistentContext() {
  System.out.println("------------testSaveSamePersistentContext(): start -------");
  Child child = new Child();
  child.setName("child");
  child.setChildId(2);
  Child childFound = genericDAO.saveAndFindRequired(child);
  System.out.println(childFound);
  System.out.println("------------testSaveSamePersistentContext(): end -------");
 }
 
}




testSaveDifferentPersistentContext() is not using Persistence Context as First Level Cache


As you can see the method testSaveDifferentPersistentContext() calls saveRequired() and findByIdRequired() methods of GenericDAO. So this is what it happens:
  1. When the method saveRequired() starts, a new transaction is created;
  2. When the method persist() of the EntityManager is invoked, a new persistence context is created. Then the child entity is inserted into this persistence context;
  3. When the method saveRequired() ends, the persistence is flushed and the transaction goes to commit;
  4. the method findByIdRequired() starts and a new transaction is created;
  5. When the method find() of the EntityManager is invoked, a new persistence context is created. Then the child entity is searched in the persistence context but it's not found;
  6. the method find() retrieves the entity by performing a query on the database.

From the database point of view, let's see the query executed.

insert into Child (name, parent_parentId, childId) values ('child', '', 1)

  select
        child0_.childId as childId1_1_,
        child0_.name as name1_1_,
        child0_.parent_parentId as parent3_1_1_,
        parent1_.parentId as parentId0_0_,
        parent1_.name as name0_0_ 
    from
        Child child0_ 
    left outer join
        Parent parent1_ 
            on child0_.parent_parentId=parent1_.parentId 
    where
        child0_.childId=1



As you can see, an INSERT and a SELECT are performed. This happens because the entity searched is not present in the persistence context (that acts as a first level cache) so you need to hit the database,

testSaveSamePersistentContext() is using Persistence Context as First Level Cache


The method testSaveSamePersistentContext() calls only the method saveAndFindRequired() of GenericDAO.
  1. When the method saveAndFindRequired() starts, a new transaction is created;
  2. When the method persist() of the EntityManager is invoked, a new persistence context is created. Then the child entity is inserted into this persistence context;
  3. When the method find() of the EntityManager is invoked, a new persistence context is created. Then and the child entity is searched in the persistence context and it's found because it has just been inserted;
  4. when the method saveAndFindRequired() method ends, the persistence is flushed and the transaction goes to commit.
From the database point of view, let's see the query executed.

insert into Child (name, parent_parentId, childId) values ('child', '', 2)

As you can see only an insert is performed. This happens because the entity searched is present in the persistence context (that acts as a first level cache) so you don't need to hit the database.

Friday, July 27, 2012

Design Pattern Adapter

In the next days i'm going to talk about the most important design patterns used in java programs.
In this post i'll show the design pattern Adapter that is a structural design pattern as Bridge and Composite.

Problem


The design pattern Adapter faces the problem of transforming an "incompatible" interface of an object into another interface expected by the client.

Solution


The design pattern Adapter suggests to resolve the problem by giving to the object with the incompatible interface an interface as the client expects.

Components


  • Target: it defines an interface into the application domain and it's a possible candidate to be called by a client;
  • Adapter: it adapts the interface of Adaptee object to the Target interface;
  • Adaptee: it defines an existing interface that needs to be adapted;
  • Client: communicates with the objects that adhere with the Target interface .


Class Adapter


The Adapter class becomes a subclass of the Adaptee class and it implements the Target interface.
At this way the client can invoke a method of the Adapter class because it adheres with the Target interface and it preserves the functionalities of the existing Adaptee class.

Object Adapter


UML Rappresentation



Object Adapter


The Adapter object has a reference to the Adaptee object and it implements the Target interface.
When a client invokes a method of the Adapter interface it delegates the Adaptee a part or all of the responsibility to serve the request method.

UML Rappresentation


Consideration


Generally the design pattern Adapter is used when you're interested into exposing to a client a functionality that you know to be present in your application domain. Unfortunately the object that exposes this functionality has an incompatible interface so it cannot be called by the client.
So you have to convert the incompatible interface of your object into another interface known by the client.

Monday, July 23, 2012

Liferay Porlet Phases

In this post we'll see only a short description of the four phases of a portlet:
  • Render Phase;
  • Action Phase;
  • Resource Phase;
  • Event Phase.


Render Phase

In the Render Phase a portlet generates HTML content of its current state. This phase is invoked for all the portlet in a page when you reach that page in your navigation and after an action phase occurs on a portlet in that page. In the specification no order for the render phase of the portlets is guaranteed.

Action Phase

In the Action Phase a portlet executes functionalities that modify its state as a database update. Generally an Action Phase doesn't return nothing.
That phase can be only invoked one at a time for a portlet. This phase is planned for all the actions that cannot be repeated as a database insert, a preference modification and so on.

Resource Phase

In the Resouce Phase a portlet serves resources like PDF, DOC, etc..

Event Phase

In the Event Phase a portlet answers to events.

Conclusion

When a user interacts with a portlet performing an action, the portlet container has to delegate that action to that portlet and then it has to render the whole page. When a portlet goes to action phase, the other portlets have to go to their render phase. So you have to be carefull on the back-end functionalities involved in render and action phases

Sunday, July 22, 2012

PL/SQL Create a Package with Functions - Tutorial

In this post i'll show the syntax to write a function in PL/SQL.

CREATE TABLE

table.sql

create table employee (
   id numeric,
   name varchar2(30),
   salary numeric,
   CONSTRAINT impiegati_pk PRIMARY KEY (id)
);



CREATE PACKAGE SPECIFICATION

PackEmployee.pks
DROP PACKAGE myschema.pkg_mypackage;

CREATE OR REPLACE PACKAGE myschema.pkg_mypackage
IS

FUNCTION get_num_employee_by_name (employee_name in varchar2) RETURN number;

END pkg_mypackage;



CREATE PACKAGE BODY

PackEmployee.pkb

CREATE OR REPLACE PACKAGE BODY myschema.pkg_mypackage
IS

FUNCTION get_num_employee_by_name (employee_name in varchar2)
 RETURN number
 IS
      return_value   NUMBER := 0;
      strSQL         varchar2(3000) := '';
  
 BEGIN

     strSQL := strSQL ||'  SELECT count(imp.id)';

     strSQL := strSQL ||'  FROM employee emp ';

     strSQL := strSQL ||'  WHERE emp.name = '''|| employee_name ||'''';
      
 EXECUTE IMMEDIATE strSQL INTO return_value;

return return_value;

 END get_num_employee_by_name;


END pkg_mypackage;




INVOKE FUNCTION OF PACKAGE

invoke.sql

select myschema.pkg_mypackage.get_num_employee_by_name(‘Simone’)
from dual

PL/SQL Cursor loops


In this post i'll show a short snippet of code about loops with cursors in PL/SQL (Procedural Language/Structured Query Language) language.

A simple way to do a loop in PL/SQL language is to use cursors as shown below.

Cursor loop

for myrec in (select col1, col2 from table A)

loop
       /* here you can use myrec.col1 or myrec.col2 to access and manage fields */
end loop;


Friday, July 20, 2012

Last Executed Query in Oracle

Not so long ago I faced to the need of knowing the last SQL queries executed in oracle. Now i'm going to post the sql query that helped me solving that problem.
Oracle Query

select * from v$sql  where sql_text like 'select%' order by first_load_time desc

Tuesday, July 10, 2012

Callable and Executor (java.util.concurrent)

Callable


Callable interface has a similar behaviour of Runnable interface except for the fact that Callable has a generic method public T call(); with a return type.
You can imagine Callable interface as a task to be executed, so when you have to choose tasks and their responsibilities, you are choosing what an instance of Callable should do.

In this example we'll see a program that counts the pair numbers in a List of Integer.
To perform a quick search I have divided the list into two sublists and I assigned two tasks to search the former the head and the latter the tail of the list. Each task returns a sub-total of the count so then we have to sum these sub-totals and print the result.
It's not a good example of concurrency but it's only a way to talk about some features of java.util.concurrent package.

ExecutorService


In this example, I make use of the interface ExecutorService that provides methods to manage the start and the termination of each task.
ExecutorService permits to return for each task (Callable) a Future object that represents a pending result of a specific Callable instance.
I put each instance of Future in a list and then I ask the result to each instance of Future using get() method.

When all the instances of Future in that list return a value, I will use these values to obtain the total count.
You have to notice that ExecutorService is obtained with a static method called Executors.newFixedThreadPool(int numThread) whose numThread value represents the max number of threads to be used by the submitted tasks or Callable instances.

It's important to notice the difference between threads and tasks. The number of threads is not directly linked to the number of tasks: the number of threads is a choice that has different reasons from the number of task which is instead linked to the specific problem you are going to resolve.

MyPairCallable.java

import java.util.List;
import java.util.concurrent.Callable;

public class MyPairCallable implements Callable<Integer> {

 private int count = 0;

 private List<Integer> list;

 public MyPairCallable(List<Integer> list) {
  this.list = list;
 }

 public Integer call() throws Exception {
  for (Integer i : list) {
   if (i % 2 == 0) {
    count++;
   }
  }
  return count;
 }

}
This method returns an Integer which is subtotal of the count of the pair number in the original list.

Main.java

...

public class Main {

 public static void main(String[] args) {

  List<Integer> list = new LinkedList<Integer>();
  for (int i = 0; i < 1000; i++) {
   //int d = (int)(Math.random()*100);
   list.add(i);
  }
  System.out.println(list.size());
  List<Integer> subListFirst = list.subList(0, list.size()/2);
  List<Integer> subListSecond = list.subList(list.size()/2, list.size());
  System.out.println(subListFirst.size());
  System.out.println(subListSecond.size());
  
  ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
  
  List<Future<Integer>> futures=new LinkedList<Future<Integer>>();
  futures.add(newFixedThreadPool.submit(new MyPairCallable(subListFirst)));
  futures.add(newFixedThreadPool.submit(new MyPairCallable(subListSecond)));
  int count=0;
  for(Future<Integer>future:futures){
   try {
    count=count+future.get();
   } catch (InterruptedException e) {
    e.printStackTrace();
   } catch (ExecutionException e) {
    e.printStackTrace();
   }
  }
  newFixedThreadPool.shutdown();
  System.out.println(count);
 }
}

Monday, July 2, 2012

JPA EntityManager and EntityManagerFactory

One of the most important things to know about the EntityManager interface is that it's not thread safe. If a Servlet or any kind of stateless component uses the EntityManager as a shared instance, you can encounter many problems.

EntityManager


MyServlet.java

 ...

@Entity
public class MyServlet extends HttpServlet {

  @PersistenceContext(unitName="myUnit")
  private EntityManager em;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  
   ...

}
The above snippet of code is not correct.

EntityManagerFactory


MyServlet.java

 ...

@Entity
public class MyServlet extends HttpServlet {

  @PersistenceUnit(unitName="myUnit") 
  private EntityManagerFactory factory;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

  EntityManager em = emf.createEntityManager()

   ...

}
The above snippet of code is correct.

Saturday, June 30, 2012

JPA @ElementCollection

Suppose you have an entity bean called User and this entity has a lot of nicknames. You can make the following mapping:
User.java
 ...

@Entity
public class User {

   @Id
   private int userId;

   @Column
   private String name;

   @ElementCollection
   private Set nicknames;

   public User() {
      super();
      this.nicknames = new TreeSet();
   }
 ...

}


Database point of view

create table User (
        parentId integer not null,
        name varchar(255),
        primary key (parentId)
)
create table User_nicknames (
        User_parentId integer not null,
        nicknames varchar(255)
)

alter table User_nicknames 
        add constraint FKA44D16712C2B0AD9 
        foreign key (User_parentId) 
        references User

JPA Mapping : Embedded Object

In JPA/Hibernate an embedded object resolve this question: how can you design in your application domain an object that is part of an entity bean? An embedded object is an object that it's not linked to a concrete table. An embedded object can't be directly persisted or queried because it's not an entity. It can only be persisted as part of another entity and so it doesn't need an id
Declaring an embeddable object is very simple.

Step-1: Create a class and annotate it with @Embeddable annotation


Address.java
...
@Embeddable
public class Address {
 
 @Column
 private String street;
 
 @Column
 private String cap;
 
...
}


Step-2: Use @Embedded annotation inside your entity bean


User.java
...

@Entity
public class User implements Serializable{

 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int userId;

 @Column
 private String name;

 @Embedded
 private Address address;

...

}


Database Point of View

As i said before, you cannot persist or query an embedded object. Access to Address object requires access to User. If you try to persist Address object, you obtain the following error::
java.lang.IllegalArgumentException: Unknown entity: com.simonefolinojavablog.persistence.entity.Address.
If you use hibernate.hbm2ddl.auto property to automatically create tables in the DB, only one table is created.

   create table User (
        userId integer generated by default as identity (start with 1),
        cap varchar(255),
        street varchar(255),
        name varchar(255),
        primary key (userId)
    )
}

Override column names of an embedded object


In many cases an embedded object can be shared among entities but sometimes you need some variations to the field names of the embedded object.
Employee.java

...

@Entity
public class Employee {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int employeeId;

 @Column
 private String name;

 @Embedded
   @AttributeOverrides({
     @AttributeOverride(name="street", column=@Column(name="jobstreet"))
   })
 private Address address;

   ...
 
}
JPA/Hibernate creates the table below. As you can see the column name street is converted into a column name called jobstreet. database point of view

  create table Employee (
        employeeId integer generated by default as identity (start with 1),
        cap varchar(255),
        jobstreet varchar(255),
        name varchar(255),
        primary key (employeeId)
    )
}

JPA - EntityManager : Persist Entities Part II

Persist and CascadeType.Persist


In this previous post (JPA - EntityManager : Persist Entities Part I) we have seen three examples of using of persist method from the EntityManager.
We have seen that you cannot save an entity unless you have saved its dependency beans before. In that example you could not save Child entity before having saved Parent entity.
This behaviour can be changed using CascadeType.Persist on the @ManyToOne association. This attribute performs a cascade operation of persisting parent entity when you try to persist a child entity.

Parent.java
 ...
@Entity
public class Parent {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java

 ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne(cascade=CascadeType.PERSIST)
 private Parent parent;
 
 ...
}
Now when you make the following test, you won't encounter the same problem, so Child entity will be saved successfully.

GenericDAO.java
...

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Parent parent) {
  System.out.println("------------save(): start -------");
  entityManager.persist(parent);
  System.out.println("------------save(): end -------");
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Child child) {
  System.out.println("------------save(): start -------");
  entityManager.persist(child);
  System.out.println("------------save(): end -------");
 }
}


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveEntityWithTransientAssociation() {
  System.out.println("------------testSaveEntityWithTransientAssociation(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(child);
  System.out.println("------------testSaveEntityWithTransientAssociation(): end -------");
 }

}

Friday, June 29, 2012

Spring MVC @PathVariable - Tutorial

In this post we'll see an example of the using of @PathVariable in Spring MVC. Suppose this is your controller class.
AddressBookController.java
 ...

@Controller
@RequestMapping(value = "/dao")
public class AddressBookController {

 private static Logger logger = Logger
   .getLogger(AddressBookController.class);

 @Qualifier(value = "addressBookDAO")
 @Autowired
 private AddressBookDAO addressBookDAO;

   
 @RequestMapping(value = "/contact/add/{number}", method = RequestMethod.GET)
 public void add(@PathVariable(value = "number") String number ) {
  logger.debug("add contact()----start: " + number);
  Contact contact=new Contact();
  contact.setNumber(number);
  addressBookDAO.create(contact);
  logger.debug("add contact()----end");
 }
 
}
    
As you can see you @PathVariable is used to map a method parameter with a portion of the request URI. Now if you are interested into saving a contact with a given number telephone (for example 123456), you can make a request at the following URL: http://localhost:8083/<context>/<dispatcher-servlet>/dao/contact/add/123456 .
  • <context> : it is your application context path;
  • <dispatcher-servlet> : it is the value of url-pattern tag of the spring dispatcher-servlet used in your web.xml.

JPA - EntityManager : Persist Entities Part I

In this post we'll see the method persist of Entity Manager and we'll take a look at the most common problems, you can face.
Consider the following entity beans.
Parent.java

 ...
@Entity
public class Parent {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(cascade=CascadeType.PERSIST,mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java
 ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne
 private Parent parent;
 
 ...
}


GenericDAO.java

...

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Parent parent) {
  System.out.println("------------save(): start -------");
  entityManager.persist(parent);
  System.out.println("------------save(): end -------");
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Child child) {
  System.out.println("------------save(): start -------");
  entityManager.persist(child);
  System.out.println("------------save(): end -------");
 }
}

Save a transient entity



DAOTest.java
...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveTransientEntity() {
  System.out.println("------------testTransientEntity(): start -------");
  Child child=new Child();
  child.setChildId(1);
  child.setName("child1");
  genericDAO.save(child);
  System.out.println("------------testTransientEntity(): end -------");
 }

}

Persist method of Entity Manager can be applied to a transient entity. So this test method complete successfully.

Save a detached entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveDetachedObject() {
  System.out.println("------------testSaveDetachedObject(): start -------");
  Child child=new Child();
  child.setChildId(2);
  child.setName("child2");
  genericDAO.save(child);
  child.setName("childNew");
  genericDAO.save(child);
  System.out.println("------------testSaveDetachedObject(): end -------");
 }
 
}

Persist method of Entity Manager can't be applied to a detached entity. An error occurs: org.hibernate.PersistentObjectException: detached entity passed to persist: com.simonefolinojavablog.persistence.entity.Child ;
This happens because JPA/Hibernate distinguishes between transient entities and detached entities by the id. Because i used @GeneratedValue(strategy=GenerationType.IDENTITY) the database will create the id automatically when a row is created in the database.

Save an entity that has a dependency with another transient entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;

  
 @Test
 public void testSaveEntityWithTransientAssociation() {
  System.out.println("------------testSaveEntityWithTransientAssociation(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(child);
  System.out.println("------------testSaveEntityWithTransientAssociation(): end -------");
 }
 
}

}

Persist method of Entity Manager can't be be applied to a transient entity that has a dependency with another transient entity. An error occurs: object references an unsaved transient instance - save the transient instance before flushing: com.simonefolinojavablog.persistence.entity.Child.parent -> com.simonefolinojavablog.persistence.entity.Parent
This exception occurs because we have to persist the Parent entity before persisting Child entity. You cannot persist an entity that has references with a transient entity but you can if this entity is a detached entity.

Suggested Pages