Google

Oct 31, 2012

Sharing and reusing objects with the flyweight design pattern in Java

The Builder pattern is used to create many objects, whereby the Flyweight pattern is about sharing such a collection of objects. The flyweight design pattern is a structural pattern used to improve memory usage and performance (i.e. due to shorter and less frequent garbage collections). Here, instead of creating a large number of objects, we reuse the objects that are already created. With fewer objects, your application could fly.

Q. Can you give some examples of the usage of the flyweight design pattern in Java?
A.

Example 1: In Java, String objects are managed as flyweight. Java puts all fixed String literals into a literal pool. For redundant literals, Java keeps only one copy in the pool.


 
  String author = "Little brown fox";
  String authorCopy = "Little brown fox";

  if(author == authorCopy) {
    System.out.println("referencing the same object");
  } 

The above code snippet will print "referencing the same object". Even though the two String objects are created separately, under the covers Java is storing them in the same location, to save space by applying the flyweight design pattern.


Example 2: The Wrapper classes like Integer, Float, Decimal, Boolean, and many other classes having the valueOf static factory method applies the flyweight design pattern to conserve memory by reusing the objects.

 public class FlyWeightWrapper {

 public static void main(String[] args) {
  Integer value1 = Integer.valueOf(5);
  Integer value2 = Integer.valueOf(5);

  if (value1 == value2) {
   System.out.println("referencing the same object");
  }

 }

}

The above code snippet will print "referencing the same object".

Q. How will you apply this pattern in the following scenario?

You have a scheduling application where a number of different time slots are used in 15 minute intervals in various online reporting. It contains hour and minute slots as in  10:15, 10:30, etc. The objects need to be immutable and reusable.

A. Here is the sample code that makes use of the getInstance(...)  static factory method to create objects.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


//no setters, immutable object
//final class -- don't let outsiders extend
public final class Schedule {

 private byte hour;
 private byte minute;
 
 private static Map<String,Schedule> schedules = new ConcurrentHashMap<String,Schedule>();

  // Don't let outsiders create new factories directly
 // can be invoked only via getInstance (byte hour, byte minute) method
 private Schedule(byte hour, byte minute) {
  this.hour = hour;
  this.minute = minute;
 }

 public byte getHour() {
  return hour;
 }

 public byte getMinute() {
  return minute;
 }
 
  public static Schedule getInstance(byte hour, byte minute) {
    String key = hour + ":" + minute;
    //check the object pool first
       Schedule schedule = schedules.get(key);
       //if not found in the pool, create a new instance
       if (schedule == null) {
        schedule = new Schedule(hour, minute);
        // add it to the pool, for later reuse
        schedules.put(key, schedule);
       }
       return schedule;
    }

}




Q. Are there any alternatives to using an object or resource pool to conserve memory in Java?
A. Yes, you can use a ThreadLocal object to create an object per thread. This approach is useful when creation of a particular object is not trivial and the objects cannot be shared between threads. For example, java.util.Calendar and java.text.SimpleDateFormat. Because these are heavy objects that often need to be set up with a format or locale, it’s very tempting to create it with a static initializer and stick the instance in a static field. Both of these classes use internal mutable state when doing date calculations or formatting/parsing dates. If they are called from multiple threads at the same time, the internal mutable state will most likely do unexpected things and  give you wrong answers. In simple terms, this will cause thread-safety issues that can be very hard to debug.

Here is an example with the ThreadLocal class to create per thread heavy object applying the abstract factory and singleton design patterns.

//final class -- don't let outsiders extend
public final class CalendarFactory {
  private ThreadLocal<calendar> calendarRef = new ThreadLocal<calendar>() {
    protected Calendar initialValue() {
      return new GregorianCalendar();
    }
  };
  
  private static CalendarFactory instance = new CalendarFactory();

  public static CalendarFactory getFactory() { 
     return instance; 
  }

  public Calendar getCalendar() {
    return calendarRef.get();
  }

  // Don't let outsiders create new factories directly
  private CalendarFactory() {}
}


Another alternative is to create immutable objects as they are inherently thread-safe, and can be shared with multiple threads.


Other design patterns - real life examples

Labels:

Oct 24, 2012

Caching Data in Java and LRU strategy


Q. What is the purpose of using a cache?
A. A cache is an area of local memory that holds a copy of frequently accessed data that is otherwise expensive to get or compute. Examples of such data include a result of a query to a database, a disk file or a report. Caching is used primarily for performance and scalability. It is a mechanism by which subsequent requests for the data are served faster.

Avoid the anti-pattern or pitfall of "Cache Them All", and cache only the data that is hard to get.

Q. What are some of the requirements you need to consider when writing your own cache or using a cacheing framework like EHCache, OSCache, etc?
A.
  1. The cache needs to have some boundary conditions defined to limit the memory usage. Each item in the cache can consume unbounded amounts of memory, hence the cache should hold its values using WeakReferences, which makes it possible for the cache to evict entries when memory is short, even when the cache is not full or the boundary conditions are not met.
  2. You need to have a replacement algorithm to purge entries from a cache when the boundary conditions are reached.  For example, reaching the maximum number of entries allowed. One such algorithm  is LRU (Least Recently Used). In this algorithm cache entries which have not been accessed recently will be replaced. If you are writing your own cache, one approach is to maintain  a timestamp at which the entry was inserted and select the entry with the oldest timestamp to be removed. But this search would be linear taking O(N) time. A more efficient approach would be to maintain the entries in a sorted collection based on the order in which the entries were accessed. Alternatively, you can use a doubly linked list where the items that are accessed via the cache are moved towards the end of the list, and purging of the entries in the cache are done from the front of the list.  
  3. Some caches need to be regularly refreshed to prevent them from becoming stale. This can be accomplished by adding an expiry timestamp. 
  4. If you are writing your own caching mechanism, then the cache item insertion and lookup operations need to be fast preferably O(1) time. This means a HashMap will be a potential candidate. The cached data can be accessed concurrently, hence a ConcurrentHashMap or a SynchronizedMap will be a good candidate. The cache should not be locked when an entry is searched, and only the searched entry should be locked. In the scenario where multiple threads search for the same key, the computation of the key value should be performed only once.


So, this is why you need to apply the "don't reinvent the wheel" principle and favor utilizing a proven and tested caching frameworks like EHCache that takes care of better memory management with LRU and FIFO eviction strategies, disk overflow, data expiration and many other optional advanced features, as opposed to writing your own. Having said this, there are cases where you might want to write your own simple caching solution or you might be asked in job interviews with questions like -- How will you implement an LRU cache in Java?

This is is very similar to the question, if Java did not have a HashMap class, how will you go about implementing your own? This was discussed with the answer and key considerations in the book "Core Java Career Esentials"


Q. What are the differences between HashMap, TreeMap (i.e. SortedMap), and a LinkedHashMap?
A. All three classes implement the Map interface and offer mostly the same functionality. The differences are in how the entries are iterated through

  • HashMap does not offer any guarantees about the iteration order. Its iteration order can change completely when new elements are added.
  • TreeMap will iterate according to the "natural ordering" of the keys according to their compareTo( ) method or based on an externally supplied Comparator. Additionally, it implements the SortedMap interface, which contains methods that depend on this sort order.
  • LinkedHashMap will iterate in the order in which the entries were put into the map.  The LinkedHashMap also provides a great starting point for creating a LRU Cache by overriding the removeEldestEntry( ) method. This lets you create a Cache that can expire data using some criteria that you define.

Q. What are the different types of algorithms that can be used to remove objects from the cache?
A. A variety of cache expiration mechanisms can remove objects from a cache. These algorithms are based on criteria such as least frequently used (LFU), least recently used (LRU), most recently used (MRU), first in first out (FIFO), last access time, and object size. Each algorithm has advantages and disadvantages. So, analyse your requirements and choose the most appropriate one.

In enterprise applications, object caching in a cluster is important because multiple JVMs run in a cluster, and it is crucial to keep all the cluster members' cached data in sync.


Q. How will you implement an LRU cache in Java?
A. Here is the sample code in Java

Firstly, define an interface so that the implementation can be changed  if for example,  in future you have a ConcurrentLinkedHashMap class.  A typical interface for a Java cache will look like

public interface LRUCache<K,V> {
   public abstract V put(K key, V item);
   public abstract V get(K key);
   public abstract V atomicGetAndSet(K key, V item); 
}


Now, the implementation class.

import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.Map;

public class LRUCacheImpl<K, V> implements LRUCache<K, V> {

 //SoftReference is used for a memory friendly cache. 
 //the value will be removed under memory shortage situations and 
 //the keys of the values will be removed from the cache map. 
 private final Map<K, SoftReference<V>> cache;

 
 public LRUCacheImpl(final int cacheSize) {

  // 'true'  uses the access order instead of the insertion order.
  this.cache = new LinkedHashMap<K, SoftReference<V>> (cacheSize, 0.75f, true) {
   
   private static final long serialVersionUID = 1L;

   @Override
   protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) {
    // When to remove the eldest entry i.e Least Recently Used (i.e LRU) entry
    return size() > cacheSize; // Size exceeded the max allowed.
   }
  };
 }

 @Override
 public V put(K key, V value) {
    SoftReference<V> previousValueReference = cache.put(key, new SoftReference<V>(value));
    return previousValueReference != null ? previousValueReference.get() : null;
 }

 @Override
 public V get(K key) {
     SoftReference<V> valueReference = cache.get(key);
     return valueReference != null ? valueReference.get() : null;
 }

 @Override
 public V atomicGetAndSet(K key, V value) {
    V result = get(key);
    put(key, value);
    return result;
 }

}


Here some key points on the above code that are worthy of mentioning not only in the job interviews to stand out from your competition, but also to write quality code and get thumbs up in the code reviews.

  1. The above code would have been written as  LRUCacheImpl<K, V>extends LinkedHashMap<K, V>, but the GoF design pattern favors composition over inheritance as inheritance is more fragile to changes.
  2. SoftReference is  used as opposed to the hard reference, to force the items to be garbage collected when the Java heap runs low in memory.
  3. The methods are synchronized to be thread-safe. In future, if a ConcurrentLinkedHashMap were to be added, then it can be used instead the LinkedHashMap.
  4. If performance is of utmost importance is of utmost importance, then the public V get(K key)  method can be executed asynchrously via a thread pool as this method will get frequently executed.

Q. What are the different types of caches?
A. There are different types of caches
  • An application cache is a cache that an application accesses directly. An application benefits from using a cache by keeping most frequently accessed data in memory. This is also known as the first level cache. For example, Hibernate can use EHCache, OSCache, SwarmCache, or JBoss TreeCache as its first level cache.
  • Level 2 (aka L2) cache  provides caching services to an object-relational mapping (ORM) framework or a data mapping (DM) framework such as Hibernate or iBatis respectively by reducing the number of trips to the database. An L2 cache hides the complexity of the caching logic from an application.
  • In memory Data Grids/Clouds for distributed caching with powerful analysis and management tools to give you a complete solution for managing fast-changing data in multiple servers, compute grid, or in the cloud. For example, Apache HadoopGridGain, Oracle Cherence, etc. A data grid is a reliable distrbuted cache that uses an external data source to retrieve data that is not present in the cache and an external data store to write the updates. In simple terms, grid or cloud computing is all about setting up an HTTP server to farm out requests RESTfully, and accept responses the same way. You can also use messaging with JMS, RMI or even the old-school Corba. But why reinvent the wheel when there are open-source frameworks like Hadoop, GridGain, Hazelcast, etc. 

Q. Will WeakHashMap make a good cache? Explain your answer?
A. No. There are 2 reasons for it.

  1.  It uses weak references as the underlying memory management mechanism. If the garbage collector determines that an object is weakly reachable, it will clear atomically all weak references to the object., whereas if the garbage collector determines that an object is softly reachable (i.e. uses a soft reference as opposed to a weak refrence), it may clear atomically all soft references to the object, in the case that it finds that memory is running low, or at its own discretion.
  2. In a WeakHashMap, the weak references are used for the keys and not for the values. You want the map values to use a weaker reference.


Q. Where would you use a WeakHashMap ?
A. It is good to implement canonical maps where you can associate some extra information to an object that you have a strong reference to. You put an entry in a WeakHashMap with the object as the key, and the extra information as the map value. This means, as long as you keep a strong reference to the object, you will be able to check the map to retrieve the extra information, and once you release the object, the map entry will be cleared and the memory used by the extra information will be released.

Labels:

Oct 18, 2012

soapUI Tutorial to test Web Services

This tutorial will show you how to test web services using soapUI. SoapUI provides a robust set of capabilities to test web services not only during development, but also to test the validity of deployments. It supports multiple protocols such as SOAP, REST, HTTP, JMS, etc.

 Step 1: Download and install soapUI from http://www.soapui.org/.



Step 2: Make sure that the simpleWeb.war file is deployed to the Apache Tomcat Server and is running as covered in the JAX-WS tutorial. The URL for the WSDL file is --> http://localhost:8080/simpleWeb/userservices?wsdl

Step 3: Double click on the soapUI application to open it and then select File --> New soap UI Project. Fill in the details as shown below and click "OK"


If the web service is not up, you will get an error message.

Step 4:  When you press the "OK" button, you should see the following folder structure on the LHS pane.



You can create additional requests by right clicking on "greetUser" and then selecting "New request".

Step 5: Double click on Request1 and on the RHS pane, you can see the divided window. One for the request and the other one is for the response.



When you click on the "green" arrow that is highlighted above, you will get the response back as shown below.



So, soapUI is a handy tool for testing  SOAP or RESTful based web services.  You can create different requests with different data. It can be used for functional and load testing. It is an easy to use Web service client that does not require any programming knowledge.

Labels: ,

Oct 17, 2012

SOAP (JAX-WS) Web Service Tutorial with Apache CXF, eclipse and maven

In the previous tutorial RESTful service with Apache CXF was demonstrated. This tutorial modifies the same one for SOAP based Web Service.


Step 1: You need to bring in the relevant CXF framework JAR files. The transitive dependencies will bring in the other dependent Spring jar files, JAXB jar files, and many other jar files listed in the screenshot below.

The pom.xml file is shown below:

<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>com.mytutorial</groupId>
 <artifactId>simpleWeb</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>simpleWeb Maven Webapp</name>
 <url>http://maven.apache.org</url>


 <properties>
  <cxf.version>2.2.3</cxf.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

 
  <!-- CXF SOAP Web Service JARS -->
  <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>
  

 </dependencies>
 <build>
  <finalName>simpleWeb</finalName>
 </build>
</project>


Now, if you right-mouse-click on simpleWeb,  and select "Maven --> Update Depencies", you can see all the transitively dependent jar files in the "Java Perspective" as shown below.


As you can see, it transitively brings in Spring and JAXB jars in addition to other relevant jars.

Step 2: Define the SOAP (i.e. JAX-WS) Web Service interface and implementation classes with relevant annotations.

Interface HelloUserWebService.java

package com.mytutorial.webservice;

import javax.jws.WebService;

import com.mytutorial.pojo.User;

@WebService
public interface HelloUserWebService {
 //parameter that gets passed via the URL
 User greetUser(String userName);
}

Implementation HelloUserWebServiceImpl.java

package com.mytutorial.webservice;

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

import com.mytutorial.pojo.User;

@WebService(endpointInterface = "com.mytutorial.webservice.HelloUserWebService")
public class HelloUserWebServiceImpl implements HelloUserWebService {

 
 public User greetUser(@WebParam(name="name") String userName) {
  User user = new User();
  user.setName(userName);
  return user;
 }

}


Step 3: Define the web service endpoint via cxf.xml, which internally uses the Spring framework. Define this under sr/main/resources folder under a package com.mytutorial.webservice.

<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">

  <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" />
  
  <jaxws:endpoint id="auth"
                  implementor="com.mytutorial.webservice.HelloUserWebServiceImpl"
                  address="/userservices"/>
</beans>


Step 4: The web.xml file and the User.java files are same as the RESTful Web Service tutorial. You should now have the relevant artifacts as shown below.




Step 5: Deploy the simpleWeb.war to the Tomcat server from within eclipse or from outside eclipse as described in the simple web JEE tutorial.

Step 6:  Open a wen browser like google chrome, and type the following URL -> http://localhost:8080/simpleWeb/. This will list the JAX-WS and JAX-RS  Web services that are available.



Step 7:  You can now open a WSDL (Web Services Description Language) file on the browser with the following URL --> http://localhost:8080/simpleWeb/userservices?wsdl

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HelloUserWebServiceImplService" targetNamespace="http://webservice.mytutorial.com/" xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://webservice.mytutorial.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://webservice.mytutorial.com/" version="1.0" xmlns:tns="http://webservice.mytutorial.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="greetUser" type="tns:greetUser" />
<xs:element name="greetUserResponse" type="tns:greetUserResponse" />
<xs:element name="user" type="tns:user" />
<xs:complexType name="greetUser">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="greetUserResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:user" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="user">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="greetUser">
    <wsdl:part element="tns:greetUser" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="greetUserResponse">
    <wsdl:part element="tns:greetUserResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="HelloUserWebService">
    <wsdl:operation name="greetUser">
      <wsdl:input message="tns:greetUser" name="greetUser">
    </wsdl:input>
      <wsdl:output message="tns:greetUserResponse" name="greetUserResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloUserWebServiceImplServiceSoapBinding" type="tns:HelloUserWebService">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="greetUser">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="greetUser">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="greetUserResponse">
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloUserWebServiceImplService">
    <wsdl:port binding="tns:HelloUserWebServiceImplServiceSoapBinding" name="HelloUserWebServiceImplPort">
      <soap:address location="http://localhost:8080/simpleWeb/userservices" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>



Step 8: From the above WSDL, you can either create a SOAP UI Client to test the above JAX-WS service, or write a stand-alone client Java class to test it programmatically.

package com.mytutorial.client;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.mytutorial.pojo.User;
import com.mytutorial.webservice.HelloUserWebService;

public final class SoapClientTest {

 private SoapClientTest() {
 }

 public static void main(String args[]) throws Exception {

  JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

  factory.getInInterceptors().add(new LoggingInInterceptor());
  factory.getOutInterceptors().add(new LoggingOutInterceptor());
  factory.setServiceClass(HelloUserWebService.class);
        //The URL should be externalized to a configuration file 
     factory.setAddress("http://localhost:8080/simpleWeb/userservices");
  HelloUserWebService client = (HelloUserWebService) factory.create();

  User user = client.greetUser("John");
  System.out.println("Response is: " + user.getName());

 }

}

The output will be:

15/10/2012 1:10:57 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.apache.cxf.bus.spring.BusApplicationContext@9506dc4: display name [org.apache.cxf.bus.spring.BusApplicationContext@9506dc4]; startup date [Mon Oct 15 13:10:57 EST 2012]; root of context hierarchy
15/10/2012 1:10:57 PM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
15/10/2012 1:10:57 PM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.apache.cxf.bus.spring.BusApplicationContext@9506dc4]: org.springframework.beans.factory.support.DefaultListableBeanFactory@62da3a1e
15/10/2012 1:10:57 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@62da3a1e: defining beans [cxf,org.apache.cxf.bus.spring.BusApplicationListener,org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor,org.apache.cxf.bus.spring.Jsr250BeanPostProcessor,org.apache.cxf.bus.spring.BusExtensionPostProcessor,org.apache.cxf.resource.ResourceManager,org.apache.cxf.configuration.Configurer,org.apache.cxf.binding.BindingFactoryManager,org.apache.cxf.transport.DestinationFactoryManager,org.apache.cxf.transport.ConduitInitiatorManager,org.apache.cxf.wsdl.WSDLManager,org.apache.cxf.phase.PhaseManager,org.apache.cxf.workqueue.WorkQueueManager,org.apache.cxf.buslifecycle.BusLifeCycleManager,org.apache.cxf.endpoint.ServerRegistry,org.apache.cxf.endpoint.ServerLifeCycleManager,org.apache.cxf.endpoint.ClientLifeCycleManager,org.apache.cxf.transports.http.QueryHandlerRegistry,org.apache.cxf.endpoint.EndpointResolverRegistry,org.apache.cxf.headers.HeaderManager,org.apache.cxf.catalog.OASISCatalogManager,org.apache.cxf.endpoint.ServiceContractResolverRegistry,org.apache.cxf.jaxws.context.WebServiceContextResourceResolver,org.apache.cxf.jaxws.context.WebServiceContextImpl,org.apache.cxf.binding.soap.SoapBindingFactory,org.apache.cxf.binding.soap.SoapTransportFactory,org.apache.cxf.binding.soap.customEditorConfigurer,org.apache.cxf.binding.xml.XMLBindingFactory,org.apache.cxf.ws.addressing.policy.AddressingAssertionBuilder,org.apache.cxf.ws.addressing.policy.AddressingPolicyInterceptorProvider,org.apache.cxf.ws.addressing.policy.UsingAddressingAssertionBuilder,org.apache.cxf.transport.http.policy.HTTPClientAssertionBuilder,org.apache.cxf.transport.http.policy.HTTPServerAssertionBuilder,org.apache.cxf.transport.http.policy.NoOpPolicyInterceptorProvider,org.apache.cxf.transport.http.ClientOnlyHTTPTransportFactory]; root of factory hierarchy
15/10/2012 1:10:58 PM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://webservice.mytutorial.com/}HelloUserWebServiceService from class com.mytutorial.webservice.HelloUserWebService
15/10/2012 1:10:58 PM org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback onClose
INFO: Outbound Message
---------------------------
ID: 1
Address: http://localhost:8080/simpleWeb/userservices
Encoding: UTF-8
Content-Type: text/xml
Headers: {SOAPAction=[""], Accept=[*/*]}
Payload: John
--------------------------------------
15/10/2012 1:10:59 PM org.apache.cxf.interceptor.LoggingInInterceptor logging
INFO: Inbound Message
----------------------------
ID: 1
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text/xml;charset=UTF-8], Date=[Mon, 15 Oct 2012 02:10:59 GMT], Content-Length=[236], Server=[Apache-Coyote/1.1]}
Payload: John
--------------------------------------
Response is: John








Labels:

Oct 15, 2012

Restful Web Service Tutorial with Apache CXF

Nowadays, it is more common to work with RESTful Web Service than with SOAP based Web service. This is also a very popular job interview question and I have discussed the reasons at Web Services Interview Questions and Answers. Apache CXF is a popular framework for developing both style Web services. This tutorial extends the "simple Web" Java EE tutorial.

Step 1: You need to bring in the relevant CXF framework JAR files. The transitive dependencies will bring in the other dependent Spring jar files, JAXB jar files, and many other jar files listed in the screenshot below.

Modify the pom.xml file as shown below:

<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>com.mytutorial</groupId>
 <artifactId>simpleWeb</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>simpleWeb Maven Webapp</name>
 <url>http://maven.apache.org</url>


 <properties>
  <cxf.version>2.2.3</cxf.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

 
  <!-- CXF RESTful Web Service JARS -->
  <dependency>
   <groupId>org.apache.cxf</groupId>
   <artifactId>cxf-rt-frontend-jaxrs</artifactId>
   <version>${cxf.version}</version>
  </dependency>
  

 </dependencies>
 <build>
  <finalName>simpleWeb</finalName>
 </build>
</project>


Now, if you right-mouse-click on simpleWeb,  and select "Maven --> Update Depencies", you can see all the transitively dependent jar files in the "Java Perspective" as shown below.



As you can see, it transitively brings in Spring and JAXB jars in addition to other relevant jars.

Step 2: Define the RESTful Web Service interface and implementation classes with relevant annotations

Interface HelloUserWebService.java

package com.mytutorial.webservice;

import com.mytutorial.pojo.User;

public interface HelloUserWebService {
 //parameter that gets passed via the URL
 User greetUser(String userName);
}


Implementation HelloUserWebServiceImpl.java

package com.mytutorial.webservice;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import com.mytutorial.pojo.User;

@Path("userservice/1.0")
@Produces("application/xml")
public class HelloUserWebServiceImpl implements HelloUserWebService {

 @GET
 @Path("/user/{userName}")
 public User greetUser(@PathParam("userName") String userName) {
  User user = new User();
  user.setName(userName);
  return user;
 }

}


Note: The path "userservice/1.0" and  "/user/{userName}" will be used in the URL when invoking the web service. For example, http://localhost:8080/userservices/userservice/1.0/user/John. The "1.0" is the web service version number.

Step 3: Define the "User" bean (or POJO -- Plain Old Java Object) class with the relevant annotations to marshall (i.e. convert object to XML) User object to relevant XML. Generally, these objects can be generated from a XSD file and running it through "xjc" compiler supplied with JAXB. This is demonstrated at "RESTful Web Service Overview".

package com.mytutorial.pojo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "user")
public class User {

 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
}


This will marshal the user object to XML like

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user>
  <name>John</name>
</user>





Step 4: Define the web service endpoint via cxf.xml, which internally uses the Spring framework. Define this under sr/main/resources folder under a package com.mytutorial.webservice.

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://cxf.apache.org/jaxrs
                        http://cxf.apache.org/schemas/jaxrs.xsd">

 <import resource="classpath:META-INF/cxf/cxf.xml" />
 <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
 <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />


 <bean id="helloUserWebService" class="com.mytutorial.webservice.HelloUserWebServiceImpl" />

 <jaxrs:server id="userRestfulWebService" address="/userservices/">
  <jaxrs:serviceBeans>
   <ref bean="helloUserWebService" />
  </jaxrs:serviceBeans>
  <jaxrs:extensionMappings>
   <entry key="xml" value="application/xml" />
  </jaxrs:extensionMappings>
 </jaxrs:server>

</beans>


Step 5: Define the web.xml with the CXFServlet and tell where to find the cxf.xml file.

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">

 <display-name>CXF Web Service Application</display-name>

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:com/mytutorial/webservice/cxf.xml</param-value>
 </context-param>
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <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>


You should now have the relevant artifacts as shown below.




Step 6: Deploy the simpleWeb.war to the Tomcat server from within eclipse or from outside eclipse as described in the simple web JEE tutorial.


Step 7: Open a wen browser like google chrome, and type the following URL -> http://localhost:8080/simpleWeb/. This will list the RESTful services that are available.

 Click on the wadl (i.e. Web Application Description Language) link to get



Step 8: Finally, invoke the web service via the URL --> http://localhost:8080/simpleWeb/userservices/userservice/1.0/user/John to get an output as shown below. The username supplied is "John". If you are accessing it via a Java application, you can use a framework like Apache HttpClient to make an HTTP call.



Labels:

Oct 11, 2012

Spring DI (aka IOC) Tutorial

Thus Spring tutorial is an extension to the Hibernate tutorial where the CourseDao is injected via Spring as opposed to directly instantiating it.

Step 1: As demonstrated in other tutorials, the first step is to have the relevant Spring framework dependency jar files. This is where Maven comes in handy to download and manage dependencies. The pom.xml file in the previous tutorial needs to now include Spring framework related jar files. I have also cleaned up the pom file by defining the version numbers via properties.



<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.mytutorial</groupId>
 <artifactId>simple</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>simple</name>
 <url>http://maven.apache.org</url>

    <!-- define the version numbers -->
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <junit.version>3.8.1</junit.version>
  <hsqldb.version>2.2.8</hsqldb.version>
  <hibernate.version>3.2.6.GA</hibernate.version>
  <hibernate-annotations.version>3.3.1.GA</hibernate-annotations.version>
  <spring.version>3.0.5.RELEASE</spring.version>


 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>${junit.version}</version>
   <scope>test</scope>
  </dependency>

  <!-- jar that contains the HSQLDB driver class -->
  <dependency>
   <groupId>org.hsqldb</groupId>
   <artifactId>hsqldb</artifactId>
   <version>${hsqldb.version}</version>
  </dependency>

  <!-- GA means General Availability -->
  <!-- Hibernate framework JARS -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate</artifactId>
   <version>${hibernate.version}</version>
  </dependency>

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-annotations</artifactId>
   <version>${hibernate-annotations.version}</version>
  </dependency>


  <!-- Spring 3 dependencies -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${spring.version}</version>
  </dependency>

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

 </dependencies>
</project>


If you right-mouse-click on the folder "simple", and then select "Maven --> Update Dependencies" you should see the relevant JARs added as shown below.


Step 2: Next step is to define your beans that you want to inject via a XML configuration file know as the spring application context. This file goes in the src/main/resources folder. Make sure this folder is in the classpath. If it is not, right-mouse-click on the "resources" folder and then select "Build Path --> Use as Source Folder". Here is the Spring configuration file simpleContext.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 <bean id="courseDao" class="com.mytutorial.dao.CourseDaoImpl" />
  
</beans>

Step 3: Redefine the HibernateTutorial  class to use Spring.

package com.mytutorial;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mytutorial.dao.CourseDao;

public class HibernateTutorial {
 
 public static void main(String[] args) {
  
  //bootstrap spring via its context file
  ApplicationContext context = new ClassPathXmlApplicationContext(
    "simpleContext.xml");
  
  CourseDao cDao = (CourseDao)context.getBean("courseDao");
  cDao.readAllCourses();
 }

}


As you can see, CourseDao is injected via Spring. That's all to it. In reality, there will be a service layer between the DAO layer (e.g. CourseDao) and the class that makes use of the service (e.g. HibernateTutorial). Let's look at this scenario to understand and appreciate DI (i.e. Dependency Injection) and how Spring does it.

Step 1: Define the service interface and implementation classes CourseService and CourseServiceImpl respectively.

The interface CourseService

package com.mytutorial.service;

public interface CourseService {
    abstract void listAllEnrolments();
}


The implementation  CourseServiceImpl

package com.mytutorial.service;

import com.mytutorial.dao.CourseDao;

public class CourseServiceImpl implements CourseService {
 
 //the implementation is injected via Spring's setter injection
 CourseDao dao;

 public void listAllEnrolments() {
  dao.readAllCourses();
 }

 public CourseDao getDao() {
  return dao;
 }

 //Spring IOC container invokes this method
 public void setDao(CourseDao dao) {
  this.dao = dao;
 }
 
}

Step 2: Modify the HibernateTutorial to inject the CourseService and CourseDao will be injected via the modified Spring configuration shown in Step 3.

package com.mytutorial;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mytutorial.service.CourseService;

public class HibernateTutorial {
 
 public static void main(String[] args) {
  
  //bootstrap spring via its context file
  ApplicationContext context = new ClassPathXmlApplicationContext(
    "simpleContext.xml");
  
  CourseService cService = (CourseService)context.getBean("courseService");
  cService.listAllEnrolments();
 }

}

Step 3: The config file simpleContext.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 <bean id="courseDao" class="com.mytutorial.dao.CourseDaoImpl" />
 
 <bean id="courseService" class="com.mytutorial.service.CourseServiceImpl">
      <property name="dao" ref="courseDao" />
 </bean>
  
</beans>





Spring is vast, and I have covered more step by step Spring tutorials at Spring concepts and step by step tutorial style examples.

Labels:

Oct 10, 2012

Hibernate tutorial with HSQLDB

This tutorial is basically an extension to the "simple" Java and JDBC tutorials. Hibernate is an ORM (Object to Relational Mapping) tool.

Step 1:  First step is to bring in the relevant Hibernate framework jar files like hibernate-xxx.jar, hibernate-annotations-xxxx.jar, and other dependent jar files that are transitively brought in from hibernate framework's pom.xml file. Here is the pom.xml file for simple Java project extended for hibernate.

<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/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.mytutorial</groupId>
 <artifactId>simple</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>simple</name>
 <url>http://maven.apache.org</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

        <!-- jar that contains the HSQLDB driver class  -->
  <dependency>
   <groupId>org.hsqldb</groupId>
   <artifactId>hsqldb</artifactId>
   <version>2.2.8</version>
  </dependency>

        <!--  GA means General Availability -->
        <!--  Hibernate framework JARS-->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate</artifactId>
   <version>3.2.6.GA</version>
  </dependency>

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-annotations</artifactId>
   <version>3.3.1.GA</version>
  </dependency>


 </dependencies>
</project>

Now, if you select the "simple" project and then right-mouse-click and select "Maven --> Update Dependencies".



Step 2: Hibernate uses the hibernate.cfg.xml file to configure the session factory with the database connectivity details and define your domain classes that map to to the relational database tables. This file needs to be defined in the src/main/resources folder and be in the classpath.

Create a new folder named "resources" under the "src/main" folder and then right-mouse-click on "resources" folder and then select "Build Path --> Use as Source Folder".



The contents of the hibernate.cfg.xml will include configuring the session factory to connect to the HSQLDB that we set up in the "SQL tutorial with HSQDB" tutorial.

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

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
  
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://localhost/mytestdb</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>
         
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>
         
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
 
        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
 
        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
         
        <!-- Echo all executed SQL to stdout useful for debugging if set to true-->
        <property name="show_sql">false</property>
         
        <property name="hbm2ddl.auto">validate</property>
  
        <mapping class="com.mytutorial.domain.Course"/>
         
          
    </session-factory>
</hibernate-configuration>


Step 3: The next step is to define the HibernateUtil class that bootstraps the hibernate by loading the SessionFactory via  the hibernate.cfg.xml.

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class HibernateUtil {
 
 
 private static final SessionFactory sessionFactory = buildSessionFactory();
   
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml file
         return new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            ex.printStackTrace();
            throw new ExceptionInInitializerError(ex);
        }
        
    }
  
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

}

Step 4: Next step is to define the domain Course class that maps to the "Course" database  table that was created in the "SQL  with HSQLDB" tutorial. Annotations are used for the object to relational mapping

package com.mytutorial.domain;

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


@Entity
@Table(name="Course")
public class Course {
 
 @Id
 @GeneratedValue
 @Column(name="course_id")
 private Integer id;
 
 @Column(name="name")
 private String name;
 
 @Column(name="course")
 private String course;
 
 public Course() {}

 public Integer getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getCourse() {
  return course;
 }

 public void setCourse(String course) {
  this.course = course;
 }
}


Step 5: Define the data access layer interface and the implementation class. The CourseDao is the interface and CourseDaoImpl is the implementation class that retrieves data from the database.




Define the interface.

package com.mytutorial.dao;

public interface CourseDao {
 
 abstract void readAllCourses();

}


Define the implementation class.

package com.mytutorial.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.mytutorial.HibernateUtil;
import com.mytutorial.domain.Course;

public class CourseDaoImpl implements CourseDao {

 public void readAllCourses() {
  SessionFactory sf = HibernateUtil.getSessionFactory();
  Session session = sf.openSession();
  Query q = session.createQuery("from Course");
  @SuppressWarnings("unchecked")
  List<Course> courses = q.list();
  
  for (Course course : courses) {
   System.out.println(course.getName() + " - " + course.getCourse());
  }

 }

}


Step 6: This step is to define a class with a main method that makes use of the CourseDao.

package com.mytutorial;

import com.mytutorial.dao.CourseDaoImpl;
import com.mytutorial.dao.CourseDao;

public class HibernateTutorial {
 
 
 public static void main(String[] args) {
  CourseDao cDao = new CourseDaoImpl();
  cDao.readAllCourses();
 }

}

You should now have the required Java files defined.



Step 7: Before you can run the HibernateTutorial.java, you need to make sure that the HSQL database is running with the Course database as demonstrated in the "SQL tutorial with HSQLDB".

c:\Tools\hsqldb-2.2.9\hsqldb>java -cp ./lib/hsqldb.jar org.hsqldb.server.Server
[Server@79616c7]: [Thread[main,5,main]]: checkRunning(false) entered
[Server@79616c7]: [Thread[main,5,main]]: checkRunning(false) exited
[Server@79616c7]: Startup sequence initiated from main() method
[Server@79616c7]: Loaded properties from [C:\Tools\hsqldb-2.2.9\hsqldb\server.properties]
[Server@79616c7]: Initiating startup sequence...
[Server@79616c7]: Server socket opened successfully in 198 ms.
[Server@79616c7]: Database [index=0, id=0, db=file:mydatabases/tutorialdb, alias=mytestdb] opened sucessfully in 1073 ms
.
[Server@79616c7]: Startup sequence completed in 1277 ms.
[Server@79616c7]: 2012-10-09 11:35:07.347 HSQLDB server 2.2.9 is online on port 9001
[Server@79616c7]: To close normally, connect and execute SHUTDOWN SQL
[Server@79616c7]: From command line, use [Ctrl]+[C] to abort abruptly


Step 8: The final step is to right-mouse-click on HibernateTutorial.java and then select "Run As --> Java Application".

You should get an output like:

Sam - Java
peter - J2EE
paul - JSF
jonathan - Hibernate
james - Spring
Lewis - JDBC

You should also see, hibernate logs as shown below

INFO: configuring from resource: /hibernate.cfg.xml
...
INFO: autocommit mode: false
09/10/2012 11:37:30 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:hsql://localhost/mytestdb
09/10/2012 11:37:30 AM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=sa, password=****}
....
INFO: Using dialect: org.hibernate.dialect.HSQLDialect
09/10/2012 11:37:31 AM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
....
INFO: fetching database metadata
09/10/2012 11:37:31 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: table found: PUBLIC.PUBLIC.COURSE
09/10/2012 11:37:31 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: columns: [course, name, course_id]


In the Spring 3.0 tutorial, I will extend this tutorial to show how we can use Spring to inject CourseDao into HibernateTutorial.

Labels:

Oct 9, 2012

JDBC Tutorial with HSQLDB

This assumes that you have gone through the basic SQL tutorial with HSQLDB. This tutorial extends the SQL tutorial by using JDBC (Java Data Base Connectivity) to programmatically connect to the database,  write data to the database, and read data from the database.  This is also known as the CRUD operations, which stands for Create, Read, Update, and Delete.

Step 1: You need the relevant driver jar for your database. In this tutorial I am using the HSQLDB, hence require the hsqldb-x.x.x.jar. Go to the maven repository (http://search.maven.org) and note down the GroupId, ArtifactId, and the Version.



Step 2: Open the "Simple" Java tutorial within eclipse and add this dependency jar  to your pom.xml file as shown below.

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mytutorial</groupId>
  <artifactId>simple</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>simple</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
     <dependency>
      <groupId>org.hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.2.8</version>
    </dependency>    
    
  </dependencies>
</project>




Once you have updated the pom.xml file, right-mouse-click on "simple" project to bring up the context menu, and then select "Maven --> Update Dependencies". This will display hsqldb-2.2.8.jar under Maven Dependencies as highlighted above.

Step 3: Create the JdbcTutorial.java class file under com.mytutorial package. Chack the import statements at the top which are classes from the JDBC API.

package com.tutorial;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcTutorial {

 public Connection getConnection() {
  Connection con = null;
  try {
   //load the HSQLDB Database Driver. 
   //This gets loaded from the hsqldb-xxx.jar
   Class.forName("org.hsqldb.jdbcDriver");
  } catch (ClassNotFoundException cnfe) {
   System.out.println("ERROR: failed to load HSQLDB JDBC driver.");
   cnfe.printStackTrace();
  }
  
  try {
   //connect to the database. 
   con = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/mytestdb", "sa", ""); 
  }
  catch (SQLException e) {
   System.out.println("ERROR: failed to connect to the databse");
   e.printStackTrace();
  }
  
  return con;
 }
 
 
 public void executeInsertQuery(Connection con) {
  PreparedStatement ps = null;

  try {
   ps = con.prepareStatement("INSERT INTO COURSE VALUES(?,?,?)");
   ps.setInt(1, 6);
   ps.setString(2, "Lewis");
   ps.setString(3, "JDBC");
   ps.executeUpdate(); // executes the insert query
   
  }
  catch (Exception e) {
   System.out.println("ERROR executing query: ");
   e.printStackTrace();
  }
  finally {
   try {
    //close the statement
    ps.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
  }
 }
 
 
 public void executeSelectQuery(Connection con) {
  PreparedStatement ps = null;
  
  try {
   ps = con.prepareStatement("SELECT COURSE_ID, NAME, COURSE  FROM COURSE");
   ResultSet rs = ps.executeQuery(); // read from database
   while(rs.next()){
    Integer id = rs.getInt("COURSE_ID");
    String name = rs.getString("NAME");
    String course = rs.getString("COURSE");
    System.out.println("id:" + id + ", name:" + name + ", course:" + course);
   }
   
  }
  catch (Exception e) {
   System.out.println("ERROR executing query: ");
   e.printStackTrace();
  }
  finally{
   try {
    ps.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
  }
 }


 //main method
 public static void main(String[] args) {
  
  JdbcTutorial tut = new JdbcTutorial();
  
  //1. get the connection to the database
  final Connection con = tut.getConnection();
  
  //2. Insert a record via JDBC
  tut.executeInsertQuery(con);
  
  //3. select all records from the database
  tut.executeSelectQuery(con);
  
  
  //4. close the connection to the databse
  try {
   con.close();
  } catch (SQLException e) {
   e.printStackTrace();
  }
 }

}





Step 4: Before you can execute the above code, you need to have the HSQLDB database server running and the relevant table (i.e. Course) and data inserted as illustrated in the "SQL tutorial with HSQLDB" tutorial.

Start the database server:

c:\Tools\hsqldb-2.2.9\hsqldb>java -cp ./lib/hsqldb.jar org.hsqldb.server.Server

Note: This tutorial assumes that you have created the schema and inserted the relevant data as illustrated in "SQL tutorial with HSQLDB" tutorial with "jdbc:hsqldb:hsql://localhost:9001/mytestdb", and the SQL queries executed are



a. DDL to create a table named "Course"

create table Course (course_id integer, name varchar(50), course varchar(50), PRIMARY KEY (course_id)); 

b. DML to insert a few records

insert into Course values (1,'Sam', 'Java');  
insert into Course values (2,'peter', 'J2EE');  
insert into Course values (3,'paul', 'JSF');  
insert into Course values (4,'jonathan', 'Hibernate');  
insert into Course values (5,'james', 'Spring');  



Step 5: You can now select the "JdbcTutorial.java" from eclipse and then right-mouse-click to bring up the contextual menu. Select "Run As --> Java Application". The program will start executing from the "main" method. The output will be

id:1, name:Sam, course:Java
id:2, name:peter, course:J2EE
id:3, name:paul, course:JSF
id:4, name:jonathan, course:Hibernate
id:5, name:james, course:Spring
id:6, name:Lewis, course:JDBC

Where id:6 was inserted programmatically, and the rest were inserted via the DatabaseManager as demonstrated in the SQL tutorial. The JdbcTutorial also illustrates retrieval of the data via JDBC.


JDBC, Spring, and Hibernate tutorials

Labels:

Oct 8, 2012

SQL Tutorial with HSQLDB

This assumes that you have Java setup on your machine as illustrated in the "simple" Java tutorial.

Q. Why use HSQLB?
A. It can be useful in a number of ways.
  • Easy to get started and if you are a beginner, you can acquire or sharpen your SQL and database skills.
  • It is open-sourced, hence you can use it for your self-taught projects as a database. An alternative to MySQL database.
  • It is used in commercial projects to write unit tests for your data access layer. Apache Derby database is another alternative.
  • It is used in the ensuing tutorials on JDBC and Hibernate as the database.

Step 1: Download the latest version of HSQLB from  http://hsqldb.org/. I downloaded hsqldb-2.2.9.zip at the time of writing and extracted zip files. The HSQLDB is unpacked under c:\Tools as as hown below.



Step 2: You can start the server with the following command.

c:\Tools\hsqldb-2.2.9>java -cp ./hsqldb/lib/hsqldb.jar org.hsqldb.Server

Step 3: Open up another command prompt and start the DatabaseManager, with which you can execute SQLs. If you are new to SQL, then this is handy to practice and gain some SQL skills. Note: You need to have the HSQLDB server running before you can open the DatabaseManager.

c:\Tools\hsqldb-2.2.9>java -cp ./hsqldb/lib/hsqldb.jar org.hsqldb.util.DatabaseManager




Once you press "Ok", the next window will look like



Step 4: Here you can type and execute some DDL(i.e. Data Definition Language) to create new table schema, etc and DML (i.e. Data Manipulation Language) to insert new data, etc. Type in the following commands  as grouped and press the "Execute" button.

a. DDL to create a table named "Course"

create table Course (course_id integer, name varchar(50), course varchar(50), PRIMARY KEY (course_id)); 

b. DML to insert a few records

insert into Course values (1,'Sam', 'Java');  
insert into Course values (2,'peter', 'J2EE');  
insert into Course values (3,'paul', 'JSF');  
insert into Course values (4,'jonathan', 'Hibernate');  
insert into Course values (5,'james', 'Spring');  

c. DML to select the records we just had created

select * from Course; 

You can now see the in memory table and the data by selecting the menu options View --> Refresh Tree.



Note: The syntax for these files are .properties, .lck etc. Since we have not specified any database name, it defaults to “test”.



This was a quick overview. Now, let's look at creating a named database.


HSQLDB supports three types of persistent tables, MEMORY tables, CACHED tables and TEXT tables.
I will be using the default MEMORY tables where data is held entirely in memory but any change to their structure or contents is written to the .script file. The script file is read the next time the database is opened, and the MEMORY tables are recreated with all their contents. So, the MEMORY tables are persistent. It is important to remember that the data in memory is written to the .script file when you shutdown your database properly (i.e. naturally by executing SQL “SHUTDOWN  (COMPACT | IMMEDIATELY”), the saved file will load the data into memory the next time the SQLDB server starts up. But if you stop the HSQLDB server abruptly in the command line by pressing [Ctrl] + [C] the data will not be written to the script file and consequently lost. Refer documentation for CACHED & TEXT tables.


Step 1: Cretate a file named server.properties under c:\Tools\hsqldb-2.2.9\hsqldb and type in the following database file name (i.e. tutorialdb) and the database alias name (mytestdb)

server.database.0=file:mydatabases/tutorialdb
server.dbname.0=mytestdb

You can now start the database server with the following command

c:\Tools\hsqldb-2.2.9\hsqldb>java -cp ./lib/hsqldb.jar org.hsqldb.Server




Once the server is started, you an see the following folder and files being created.



Step 2: Once the server has started, start the DatabaseManager where you can manage your schemas and data.

c:\Tools\hsqldb-2.2.9\hsqldb>java -cp ./lib/hsqldb.jar org.hsqldb.util.DatabaseManager


Note that the protocol is "hsql" and not "mem".

You can type in the relevant DDL and DML SQL queries as you did earlier. This is still an in-memory database and the data will be lost in between invocations.


Note: To persist your data from memory, you need to execute the "SHUTDOWN" SQL command, which will delete the tutorialdb.lock and and tutorialdb.log files and if you open the tutorialdb.script file, you can see your SQL commands that get executed when you reconnect again.

CREATE MEMORY TABLE PUBLIC.COURSE(COURSE_ID INTEGER PRIMARY KEY,NAME VARCHAR(50),COURSE VARCHAR(50))
ALTER SEQUENCE SYSTEM_LOBS.LOB_ID RESTART WITH 1
SET DATABASE DEFAULT INITIAL SCHEMA PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.YES_OR_NO TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.TIME_STAMP TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CARDINAL_NUMBER TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.CHARACTER_DATA TO PUBLIC
GRANT USAGE ON DOMAIN INFORMATION_SCHEMA.SQL_IDENTIFIER TO PUBLIC
GRANT DBA TO SA
SET SCHEMA SYSTEM_LOBS
INSERT INTO BLOCKS VALUES(0,2147483647,0)
SET SCHEMA PUBLIC
INSERT INTO COURSE VALUES(1,'Sam','Java')
INSERT INTO COURSE VALUES(2,'peter','J2EE')
INSERT INTO COURSE VALUES(3,'paul','JSF')
INSERT INTO COURSE VALUES(4,'jonathan','Hibernate')
INSERT INTO COURSE VALUES(5,'james','Spring')




If you want to persist it directly to a file without having an alias, you can try.



Once you know how HSQLDB works, you can work on JDBC and Hibernate tutorials.



You may also like:


Labels: