Sunday, April 12, 2009

Hibernate Assosiations :Mapping Relations

Many to One Relation

Let us take the case of Employee and Company , its a typical case for many to one relation. Many employees can belong to a single Company.

Now this relation is unidirectional

@Entity
public class Employee
{

@Id
@GeneratedValue
@Column(name = "F_EMP_ID")
private int empId;

@ManyToOne(optional = true,fetch=FetchType.EAGER)
@JoinColumn
(name = "F_EMP_CMPNY_ID",referencedColumnName="F_CMPNY_ID")
private Company company;

private String name ;
.....
.....



getter and setters for all the values ...

}

@Id : shows its primary key

@GeneratedValue : asks hibernate to generate the primary keys

@Column : to give a java name for a corresponding DB field name

@ManyToOne : shows the many to one realtionship with field company
<Company>

optional : says if this field can be null for Employee row ( true is the default value)

fetch : whether to eagerly fetch the dependent rows (of company ) when fetching employee

(LAZY if the default value , we can change it to FetchType.EAGER)

@JoinColumn - how to join the column for the realtionship

name database field of the current entity which is used for joining

referencedColumnName data base field of the joining entity used for joining
If this field is not mentioned the primary key of the joing entity is taken hence in the above example we ned not mention this value

The other entity in the relationship

@Entity
public class Company
{

@Id
@GeneratedValue
@Column(name = "F_CMPNY_ID")
private int cmpnyId;

private String cmpnyName ;

.....

getter and setters for all the values ...
}


Now in the above example the mapping is complete .Now we can use the entitymanager to fetch any row of Emlpoye entity
(as showm in the previous blog)

entityManager.find(Employee.class, id) --> gives the corresponding Employee

(Note : This statement will come under the scope of @Transactional which manages the session)

Now we can use Employee.getCompany() -> which gives the coresponding Company value

Note:

This is possible because we used fetch=FetchType.EAGER while mentioning the manytoone relation.This ensure that when the request is made for Employee the corresponding Company is also fetched from the DB.

If this option(fetch=FetchType.EAGER) was not mentioned the default one would be used ,that is (fetch=FetchType.LAZY)

Lazy initilization commands hibernate that when Employee is fetched the corresponding , the coresponding Company is not fetched . This is called lazy initilization.Hibernate tries to fetch Company only when i first request is made to the company field in the Employee instance.


Now if this request for company is made outide the scope of @Transaction , that is when no session is open , hibernate gibes a error saying it could not Lazily initialize Company because of Lazy init.

Hence care should be taken to see to that the first request to the depending Entity(in this Company )in the case of FetchType.EAGER should be made inside a valid session.

There is an alternative to get all the dependent rows , when we use Fetch.LAZY . this is by explicitly initializing hibernate.

//include this in the service which gets employee

Employee e = entityManager.find(Employee.class, id);
//this ensures that corresponding company is also fetched along with employee
Hibernate.initialize(employee.getCompany());
//employee.getCompany() -- i sthe first request to Company
return e;



Now the above relation is Unidirectional , that is employee gets Company .Now what if we want to get all the employees in a Company.

We can achive this by making it Bidirectional

We will make small chages in Company Entity to make it bidirectional

@Entity
public class Company
{

@Id
@GeneratedValue
@Column(name = "F_CMPNY_ID")
private int cmpnyId;

private String cmpnyName ;

@OneToMany(mappedBy = "company" ,fetch =FetchType.EAGER)
private List<Employee> employees;
.....



getter and setters for all the values ...
}

@OneToMany - > indicates that the relationship is onetomany with List of employess , that is this company instance can have list of employees

mappedBy -> indicates that the other side is the owner of the relation.

That is a corresponding relation is defined in Employee entity and the

Employee entity had a member variable of Company by name company

fetch =FetchType.EAGER - > defines the type of fetch (Described above)


Now this relation is bidirectional that is when we fetch a Company insatnce we will get all the employees working for it by

Company c = entityManager.find(Company.class, id);

c.getEmployees(); - will return all the emplyees working in that company



One to One mapping


NO\ow to show a one2one mapping lets take a case of Address Entity

public class Address
{

@Id
@GeneratedValue
@Column(name = "F_ADDRS_ID")
private Long id;


.....

// Getters and Setters ...
}


@Entity
public class Company
{

@Id
@GeneratedValue
@Column(name = "F_CMPNY_ID")
private int cmpnyId;

private String cmpnyName ;

@OneToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "F_CMPNY_ID", referencedColumnName = "F_ADDRS_ID")
private Address address;


getter and setters for all the values ...
}


The above relation is similar to the above mentioned many to one relation , and all the attributes for many to one also apply to this.

This relation in Unidirectional and can be made bidirectional by declaring a corresponding relation on Address Entity.

Some Interesting notes on Hibernate

When a primitive value is mapped from a java class to db table column remeber to assign default values to these in the DB ,else when null is
inserted to the column ,and when we retrieve this its gives an error saying null canot be casted to primitive members.Hence for example if null
is present in the DB to retrieve this Wrapper classes such as Integer should be used instead of int.

Though we mention relation(involving primary key) in the classes using annotaions it is also helpful to mention the primary again with indertable and
updatebale equlas false , because in certain cases we need to retrive a row(or certain fileds only) in the db just based on this value and it can be '
hence mentioned in the HQL query directly .

// @Column(name = "F_PRODUCT_CATEGORY_ID" , insertable = false , updatable = false)
// private int pSampleId;\



Still to Follow .....

Many To Many Relation ..

Hibernate Annotations & EntityManager With JPA and Spring

Hibernate is an Open Source Object Relational mapping tool which provides transparent persistence for POJOs. Object-relational mapping is used to map object-oriented programming objects to relational databases managed by Oracle, DB2, Sybase, and other relational database managers (RDBMSs)

Hibernate allows you to express queries in its own portable SQL extension (HQL), as well as in native SQL, or with an object-oriented Criteria.

Other popular ORM solutions are iBatis, JDO and TopLink.

JPA(Java Persistence API)

Java Persistence API was included as part of the Java EE 5 platform. This new API simplifies the development of Java EE and Java SE applications using data persistence. This also gets the entire Java community behind a single, standard persistence API.The Java Persistence API draws upon the best ideas from persistence technologies such as Hibernate, TopLink, and JDO.

Hibernate implements the Java Persistence object/relational mapping and persistence management interfaces with the Hibernate Annotations and Hibernate EntityManager modules, on top of the mature and powerful Hibernate Core.

Since JPA's are used for persistence in the application the ORM providers can be easily changed, in the below example it is easy to replace Hibernate with TopLink , since it will be only configuration changes. This is because we have used JPA's in our entity classes and used entitymanager and we have not stuck to any hibernate specific API's

Hibernate Annotations

Hibernate, like all other object/relational mapping tools, requires metadata that governs the transformation of data from one representation to the other (and vice versa). As an option, you can now use JDK 5.0 annotations for object/relational mapping with Hibernate 3.2. You can use annotations in addition to or as a replacement of XML mapping metadata.

You can use Hibernate extension annotations on top of standardized Java Persistence annotations to utilize all native Hibernate features.

Hence in all the below sample entities you can use of javax.persistence.* classes which are the JPA's used to indicate hibernate about the mapping it has to perform in the Database.

In the basic format of hibernate without annotations,we need to define the mapping between between a class and the Db tables using hibernate config files.

Hibernate EntityManager

It implements:

* The standard Java Persistence management API
* The standard Java Persistence Query Language
* The standard Java Persistence object lifecycle rules
* The standard Java Persistence configuration and packaging

Hibernate EntityManager wraps the powerful and mature Hibernate Core. You can fall back to Hibernate native APIs, native SQL,and native JDBC whenever necessary.

Spring For Hibernate

When used with hibernate this reduces a lot of work like obtaining session for each and every transaction .Instead we mention this using @Transaction annotation that the entitymanger needs to be transaction enabled and spring takes care of managing the session using
AOP.Spring also helps in easy configuraion of the DB and ORM into the entitymanager.

Now since we are familiar with the technologies to be used lets build a sample application

Configuration in spring.xml

Assuming we use mysql as the DB following will be the configuration.

Declaring the Datasource

<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/<DB_NAME>" />
<property name="username" value="<USER_NAME>" />
<property name="password" value="<PASSWORD>" />
</bean>


BeanPostProcessor that processes PersistenceUnit and PersistenceContext annotations, for injection of the corresponding JPA resources EntityManagerFactory and EntityManager. Any such annotated fields or methods in any Spring-managed object will automatically be injected.

This post-processor will inject sub-interfaces of EntityManagerFactory and EntityManager if the annotated fields or methods are declared as such.

PersistenceAnnotationBeanPostProcessor only supports @PersistenceUnit and @PersistenceContext

<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

This creates a JPA EntityManagerFactory according to JPA's standard container bootstrap contract. This is the most powerful way to set up a shared JPA EntityManagerFactory in a Spring application context

As with LocalEntityManagerFactoryBean, configuration settings are usually read in from a META-INF/persistence.xml config file, residing in the class path, according to the general JPA configuration contract.

The datasource is given as a parameter to the ORM(hibernate) which later if given as a parameter to JPA factory to create the entitymanager.

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>


This defines a transaction manager which is responsible for opening and closing sessions when an entity manager is used.

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>


This ensures that session management for all classes/methods marked with @Transactional are taken care by the transaction manager, that is it will take care of opening the sessions and closing them.

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

This is a directive to spring to enable annotations.

<context:annotation-config/>

JPA configuration

1. Create a folder named "META-INF" under the "src" folder.
2. Create a file named "persistence.xml" under the "META-INF" folder and set its content to:

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="punit">
</persistence-unit>
</persistence>

Now lets create a sample class in Java(Class mapping to DB table)

package test;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
@Table(name = "T_STUDENT")
public class Student {
@Id
@GeneratedValue
@Column(name = "F_ID")
private Integer id;
private String lastName;
private String firstName;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}
}

in the above class

@Entity indicates that this class will be mapped to a table in database

@Table indicates the corresponding table name in DB , if this is not mentioned the default class name will be taken

@Id Indicates the primary key to the table

@GeneratedValue - Indicates the strategy used to generate primary key for the table

@Column - indicates the corresponding column name for the filed in the DB.


Now Lets write a service to access these

Interface

package test;

import java.util.List;

public interface IStudentService {

public List<Student> findAll();

public void save(Student student);

public void remove(int id);

public Student find(int id);
}


Implementation

package test;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Transactional;


@Transactional
public class StudentService implements IStudentService {


private EntityManager em;

//This is injected by spring
@PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}


//gets all the student tuples from the DB
@SuppressWarnings("unchecked")
public List<Student> findAll() {
Query query = getEntityManager().createQuery("select s FROM Student s");
return query.getResultList();
}


//saves a touple int DB , if its already exists will update it
public void save(Student student) {
if (student.getId() == null) {
// new
em.persist(student);
} else {
// update
em.merge(student);
}
}

//deletes a touple from teh DB
public void remove(int id) {
Student student = find(id);
if (person != null) {
em.remove(student);
}
}

private EntityManager getEntityManager() {
return em;
}

//gets a tuple based on the primarykey
public Student find(int id) {
return em.find(Student.class, id);
}

}


Now the above service can be injected using spring to any action class and used to do all the required DB operations.

Saturday, April 11, 2009

Sample Tiles Application

Apache Tiles is a templating framework built to simplify the development of web application user interfaces.Tiles allows authors to define page fragments which can be assembled into a complete page at runtime.These fragments, or tiles, can be used as simple includes in order to reduce the duplication of common page elements or embedded within other tiles to develop a series of reusable templates.

Lets build a sample tiles app

Configuraion using web.xml

<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>

<context-param>
<param-name>tiles-definitions</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>


Also the configuration can be done using spring xml as follows

<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>

</bean>


Define a tiles.xml and place it under WEB-INF

tiles.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_2_0.dtd">

<tiles-definitions>
<definition name="main" template="/layouts/template.jsp">
<put-attribute name="logo" value="/tiles/logo.jsp" />
<put-attribute name="navigation" value="/tiles/navigation.jsp" />
<put-attribute name="body" value="/tiles/indexBody.jsp" />
<put-attribute name="footer" value="/tiles/footer.jsp" />
</definition>


<definition name="offer" template="/layouts/template.jsp" extends="main">
<put-attribute name="body" value="/tiles/offerBody.jsp" />
</definition>

</tiles-definitions>

Tiles also helps in inheritance as you can see

The offer tile definition extends the main definition and can override any of parts of the main definition.


The template looks as follows and can be changed for look and feel

template.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Discount Sale</title>
</head>
<body>
<div id="main">
<tiles:insertAttribute name="logo"/>
<tiles:insertAttribute name="navigation"/>
<tiles:insertAttribute name="body"/>
<tiles:insertAttribute name="footer"/>
</div>
</body>
</html>


All other jsps like logo.jsp , navigation.jsp and footer.jsp can have the logic for view as in any othet jsps.

Bug when Tomcat 6(installed in directory with spaces) and Xwork

When tomcat is installed in a directory with spaces , and used for struts application you may get a

NullPOinterException

com.opensymphony.xwork2.util.FileManager$FileRevision.needsReloading(FileManager.java:209)

This will be fixed in the future versions of the xwork jar , else you need to download the latest code from their branch and build the jar.

There is alternative to this , this error can be avoided by setting

struts.devMode=false

Wednesday, April 8, 2009

Another Bundling tool - Bundlor

This is alternative to BND which can be used to build bundles.

This tool has much more provisions , than bundlor and is provided by spring .It scans much more than just the java class file, including spring configuration files and also has support for hibernate annotations.

It also helps to add exceptions during building the bundle by using a template file.

Ref:

http://www.springsource.org/bundlor

http://blog.springsource.com/2009/03/20/getting-started-with-bundlor/

Uses directive in OSGi

Uses directive is very important when you shift to versioning of jars, that is when two bundles share the same class.

A runtime type is defined by the combination of the type's fully qualified class name and the class loader that defined the type. If the same fully qualified class name is defined by two distinct class loaders, then this produces two incompatible runtime types. This incompatibility causes runtime errors if the two types come into contact. For example, attempting to cast one of these types to the other will result in a class cast exception.

The conflict arises when one bundle(A) imports one version of the class from bundle ( B v1.0) and another bundle(C) depending on bundle A imports a class from different version of class from (B v 2.0) .

This can be solved by mentioning strict dependencies on the imports , but when the dependency tree gets huge this will be difficult to manage , and hence can be easily solved by the uses attribute.

The following article has detailed explanation on the uses attribute and how errors on that can be diagnosed.

Ref:

http://olegz.wordpress.com/documents-and-articles/osgi-uses/

http://blog.springsource.com/2008/10/20/understanding-the-osgi-uses-directive/

http://blog.springsource.com/2008/11/22/diagnosing-osgi-uses-conflicts/

Remote Debugging using Eclipse

Set these parameters on the remotely running java process

DEBUG_OPTS="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n -Djava.compiler=NONE"

where 8000 is the port on which the java process listens to debug commands from eclipse.

When the java code is compiled ensure that debug is enabled

In the case of ant set

      <javac debug="on" ....> ... </javac>

from Eclipse choose
Run -->
Debug Configurations -->
Select Your Project
Give the IP and the Port of the machine where the remote process is running.
Finally click on Debug

Now you can set break points as usual from eclipse and the window will pop up when the execution reaches that point.

Tuesday, April 7, 2009

Getting Thread Dumps or StackTraces

Stack trace can be obtained by issuing the following command

jstack <processid>

The output can also be redirected into any file.

Ref : http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstack.html

The thread dumps also can be obtained by the following command

kill -3

The thread dump will be appended to the application logs.

(Redirect the standard out (stdout) of the java command to a file. When you send a SIGQUIT signal to the java process, a thread dump is sent to the stdout)

To understand and analyse the thread dumps refer the following

http://weblogs.java.net/blog/bhaktimehta/archive/2007/05/obtaining_and_a.html

Configuring Logging for Tomcat on Eclipse

When tomcat is added as a server under Eclipse thw logs are displayed on the console and it never comes under the logs of tomcat neither in eclipse workspace.

It can be configured to do so by

Double Clicking the newly added server in the Servers menu

1. In General Information

Click Open Launch Configurations - >
-> Add the required arguments in the argument tab ,
-> and in the Common tab you can mention weather the output the to be on the console or piped int o any other log file ion the disk.

Refer this to enable JULI logging on the Server Instance

http://wiki.eclipse.org/WTP_Tomcat_FAQ#How_do_I_enable_the_JULI_logging_in_a_Tomcat_5.5_Server_instance.3F

2. In the Server Location - you can choose User Tomcat Installation which will take control on the tomcat installation directory and all application under it will also be deployed

Enabling Access Logs on Tomcat 6

Tomcat 6 has a new feature which logs access logs. This can be easily enabled by uncommenting the required code in the conf/server.xml.

<valve classname="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="common" resolvehosts="false">
</valve>

This can be embedded for the Host or per context basis

 
Free Domain Names @ .co.nr!