Search This Blog

Loading...

Saturday, June 18, 2011

JEE5: EJB3, JPA CRUD in 2 minutes


Requirements:
  1. Installed JDK 1.5 (better 1.6) 
  2. An IDE of your choice e.g.netbeans 6.1 (SE or EE), Eclipse (SE or EE), JDeveloper
  3. @Stateless, @Local, @Entity, @Id Annotations in classpath 
  4. An Java EE 5 capable application server of your choice. It will work with Glassfish v3+, JBoss 5+, WLS 10+.
What is to do:
  1. In the IDE you will have to point to a JAR containing the three annotations. If you have the Reference Implementation installed (Glassfish), put just: glassfish\lib\javaee.jar to the classpath. You will need a persistence provider as well. In case of toplink, there is only one jar: (glassfish\lib\toplink-essentials.jar). IDEs with built in EE support have already everything you need. However for the very first time I would prefer to develop "from scratch" an EJB. 
  2. Start with the Entity class. Just create a class and put @Entity tag on it:

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

    @Entity
    public class Book {

        @Id
        @GeneratedValue

        private Long id;
        private String title;

        public Book() {
        }


        public Book(String title) {
            this.title = title;
        }
    }

    The @Id @GeneratedValue annotations denote the id field as a primary key. An entity should contain a parameterless constructor as well.
  3. Setup a DataSource at the application. jdbc/sample already exists in every fresh Glassfish installation (so nothing to do here).
  4. Create an interface with CRUD methods:
    import javax.ejb.Local;
    @Local public interface BookServiceLocal {
        Book createOrUpdate(Book book);
        void remove(Book book);
        Book find(Object id);
    }
  5. Create a class which implements this interface. You will be forced by a good IDE to implement this interface:
    @Stateless
    public class BookService implements  BookServiceLocal {
        @PersistenceContext
        private EntityManager em;

        public Book createOrUpdate(Book book) {
            return em.merge(book);
        }
        public void remove(Book book) {
            em.remove(em.merge(book));
        }
        public Book find(Object id) {
            return em.find(Book.class, id);
        }
    }

    The method merge creates or updates an entity, all other methods should be self-explanatory. Hint: you cannot remove not-attached entities - you have to find them first. This is the "Seek And Destroy" pattern :-). 
  6. You have to create a small XML file. However - it will not grow:
      <persistence-unit name="sample" transaction-type="JTA">
        <jta-data-source>jdbc/sample</jta-data-source>
        <properties>
          <property name="toplink.ddl-generation" value="create-tables"/>
        </properties>
      </persistence-unit>
    </persistence>

    There is only one persistence-unit element with the name "sample". EJB 3 Dependency Injection works with the "Convention Over Configuration" principle. This allows us to keep the injection of the EntityManager very lean: if there is only one possibility - you have not to configure it.
  7. Compile everything and JAR (the persistence.xml into META-INF) the output (in Netbeans just "build", in Eclipse "Export -> JAR")
  8. Copy the JAR into the autodeploy folder of WLS 10 (bea10\user_projects\domains\YOUR_DOMAIN\autodeploy), or glassfish\domains\domain1\autodeploy in the case of Glassfish v3, or jboss-5.0.GA\server\default\deploy in case of JBoss
  9. Inspect the log files, you are done :-)
What you have gained:
  1. It's threadsafe (in multicore environments as well) 
  2. Remoting: you can access the interface remotely
  3. It's transactional - transactions are started for you
  4. It's pooled - you can control the concurrency and prevent "denial of service" attacks.
  5. It's monitored: and EJB have to be visible through JMX. Application servers provide additional monitoring services as well.
  6. Dependency Injection just works - you can inject persistence, other beans, legacy pojos (I will cover this in some upcomings posts)
  7. It's portalble and so vendor-neutral. Deployment to different application servers just works
  8. There is almost NO XML.
  9. Its easily accessible (via DI), from Restful services, JSF, Servlets etc.
  10. Clustering and security are beneficial as well - but not the main reason to use EJBs
  11. EntityManager is injected in thread-save manner.
  12. Transactions are managed for you - the EntityManager participates in the transactions (no additional setup etc. necessary)