Saturday, February 27, 2010

Android Development Tips and Issues

General
  • After importing a project created by someone else, you may need to correct the Project Build Target via project Properties -> Android panel.
UI
  • The attribute layou_height=fill_parent doesn't work as usually inside the ScrollView. Set the size explicitly, possibly using minHeight and MaxHeight.

    Friday, February 19, 2010

    JSON RESTfull Service Using Jersey with Hibernate Persistence on Glassfish

    Tips:
    • to setup Hibernate to use a datasource defined under Glassfish, see my other post.
    • usefull Jersey annotations:
      • for the resource class: @Path("/person/")
      • for a method: @GET @Path("{personId}/") @Produces("application/json"). Then, you can use public Person getUser(@PathParam("personId") int personId) for method declaration.
      • add @Consumes("application/json") with public Person post(Person person) method declaration. Jersey takes care of unmarshaling the Json into Person object.
    • to return an error code from the restfull webservice, throw a new WebApplicationException(Response.Status.NOT_FOUND), for example. This one would return 404 error. No Need to declare the jersey handler method as "throws ...".
    • to unit test the service, use com.sun.jersey.api.client.Client:
      Person result = Client.create().resource("http://localhost:8080/myapp/person")
         .type("application/json")
         .post(Person.class,new Person("Jon Smith",133));
      Assert.assertEquals("Jon Smith", result.getName()); 
    • To pass an object retrieved via Hibernate as a response from a webservice, it needs to be serializable. But objects retrieved this way have additional members and so they need to be converted to a pure entity object (Person, in my case). I have used the Dozer library for this purpose (see the code below).
    • The entity classes (Person and PersonCollection, in my example)need to be annotated with @XmlRootElement.

    Code:
    Complete web service implementation class code (in RESTfull, call a resource):
    package olcc.jersey.service;
    
    import java.util.List;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.core.Response;
    import olcc.entity.HibernateUtil;
    import olcc.entity.Person;
    import olcc.entity.PersonCollection;
    import org.dozer.DozerBeanMapper;
    import org.dozer.Mapper;
    import org.hibernate.Transaction;
    import org.hibernate.classic.Session;
    
    @Path("/person/")
    public class PersonResource {
     
     @GET @Path("{personId}/") @Produces("application/json")
     public Person getPerson(@PathParam("personId") int personId) {
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      Transaction tx = null;
      Person personClean;
      
      try{
       tx = session.beginTransaction();
       Person person = (Person) session.load(Person.class,personId);
       
       Mapper mapper = new DozerBeanMapper();
       personClean = mapper.map(person,Person.class);
    
       session.getTransaction().commit();
    
      } catch( Exception ex) {
       if( tx != null ) tx.rollback();
             throw new WebApplicationException(Response.Status.NOT_FOUND);
      }
      return personClean;
     }
     
     @GET @Produces("application/json")
     public PersonCollection get() {
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
      List<person> result = session.createQuery("from Person").list();
    
      Mapper mapper = new DozerBeanMapper();
      PersonCollection persons = new PersonCollection();
            
      for( Person person : result ) {
        persons.add(mapper.map(person,Person.class));
      }
      session.getTransaction().commit();
            
      return persons;
     }
     
     @POST @Consumes("application/json")
     @Produces("application/json")
     public Person post(Person person) {
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      session.beginTransaction();
      
      session.save(person);
      
      session.getTransaction().commit();
      return person;
     }
    
     @GET @Path("delete/{personId}/") @Produces("application/json")
     public Person deleteOne(@PathParam("personId") int personId) {
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      session.beginTransaction();
      Transaction tx = null;
            Person personClean;
      
      try{
       tx = session.beginTransaction();
       Person person = (Person) session.load(Person.class,personId);
       session.delete(person);
       
       Mapper mapper = new DozerBeanMapper();
       personClean = mapper.map(person,Person.class);
    
       session.getTransaction().commit();
    
      } catch( Exception ex) {
       if( tx != null ) tx.rollback();
             throw new WebApplicationException(Response.Status.NOT_FOUND);
      }
    
      return personClean;
     }
    }

    Open Questions:
    • I'm not sure where the Hibernate session should be closed. I don't think this can be done at the end of each handler method.
    • How to use JTA for transaction management instead of direct JDBC transaction management?
    • Most of the Hibernate-specific code should go into a DAO, with most of it into a generic DAO. But the recommended by Hibernate documentation generic DAO is defined in terms of state-oriented data access API (makePersistent() and makeTransient() methods), which are less intuitive for me. What is the advantage of using them and how to use them from CRUD operations?

    Wednesday, February 17, 2010

    Configure Hibernate to Use A Datasource

    I'm using Glassfish application server, on which (using its Console) I have created a JDBC datasource (JDBC Resource). I'd like configure the hibernate framework to use it. The resons:
    • Connection pooling (it's true that I could use the Hibernate's own connection pooling)
    • Portability: moving the application to another application server is easy, as long as they both provide a datasource with the same name (Hibernate dialect may still need to be changed appropriately).
    hibernate.cfg.xml File
    <?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 name="hibernate/sessionFactory">
            <property name="connection.datasource">jdbc/derbydb</property>
            <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
            <property name="current_session_context_class">thread</property>
            <property name="hbm2ddl.auto">create</property>
        
         <mapping resource="olcc/entity/Person.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
    


    HibernateUtil.java File
    private static SessionFactory buildSessionFactory() {
        return new Configuration().configure().buildSessionFactory();
    }
    


    The Application Code
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    
    

    Thursday, February 11, 2010

    Using Powermock to Mock Java Objects for Unit Testing

    This test uses the EasyMock style (as opposed to Mockito style), so it needed the corresponding file download. The code sample (click on view source icon to see it better):
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    import static org.easymock.EasyMock.expect;
    import static org.powermock.api.easymock.PowerMock.*;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.legacy.PowerMockRunner;
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest({Person.class })
    public class PersonResourceTest {
    
        @Test
         public void testPost() {
    
            Person personMock = createMock(Person.class);
            expect(personMock.getName()).andReturn("Jon Smith");
            replay(personMock);
    
        // do the test...        
    
            Assert.assertEquals("Jon Smith", result.name);
        }
        
    }

    Wednesday, February 10, 2010

    SQL Checks And Rules

    In most data models, there are columns that should take values only from a limited set.  For example, a state of License (as in our current project) may only take three values: AppliedFor, Granted or Denied. This kind of restriction is part of what is called Domain Level Integrity. How do you implement it?

    Old Way: Separate Table
    I used to create a separate table for the allowed values. It can be done, but this table has only couple records in it, is rarely updated and using a whole table for this is almost an overkill. Also, you end up writing more code to manipulate it.

    New Way: SQL Rules
    There is an SQL construct purpose of which is exactly this kind of constraint: SQL Rule (for Sybase docs: see this). An example:

    create rule pub_idrule 
    as @pub_id in ("1389", "0736", "0877", "1622", "1756")
    or @pub_id like "99[0-9][0-9]" 
     

    Wednesday, February 3, 2010

    Persistence Frameworks, ORMs

    The big three, I consider mainstream (from Java perspective):
    • Hibernate
    • JPA
    • JDO
     I have sorted them in the market share order, but there are some interesting facts that make all three important:
    • Hibernate is definitely the strongest, most popular ORM framework for Java and .Net, but it's not a standard per se.
    • JPA is a standard and it's fully supported by HIbernate, so choosing it gives you some advantages over Hibernate. Its design was based on Hibernate and JDO.
    • You can use Hibernate and restrict yourself to the JPA-only, which gives you a portability to another JPA-type framework, if you so choose in future.
    • JDO, although the oldest one, is the preferred persistence mechanism for Google Application Engine, the Java application hosting service of Google (although, you can also use JPA with it).
    Which framework to choose? Your choice.  Need more help choosing? Try this article.