Showing posts with label Java EE 5. Show all posts
Showing posts with label Java EE 5. Show all posts

Monday, May 07, 2007

Securing EJB 3.0 Beans

The Java EE 5 Security services are provided by the container and can be implemented using declarative or programmatic techniques. In addition to declarative and programmatic ways to implement security (in J2EE), Java EE 5 supports the use of metadata annotations for security. This post will describe how to secure EJB 3.0 beans. The post consists of a simple EJB, with a web client. In order to run the example, follow these steps.
Create Users in Glassfish
  1. Go to Configuration->Security->Realms->file in the Glassfish admin console.
  2. In the file realm, click on manage users.
  3. Add new users by clicking on add there.

The EJB Component
  1. Start with a Simple Java project in Eclipse.
  2. Remote Interface
    package ejb;

    import javax.ejb.Remote;

    @Remote
    public interface DABean {
    public String create();

    public String read();

    public String update();

    public String delete();
    }
    ejb/DABean.java
  3. The Bean:
    package ejb;

    import javax.annotation.security.DeclareRoles;
    import javax.annotation.security.RolesAllowed;
    import javax.ejb.Stateless;

    @Stateless (mappedName = "ejb/secureEJB")
    @DeclareRoles({"emp","guest"})

    public class SecureEJB implements DABean {

    @RolesAllowed({"emp","guest"})
    public String create() {
    return "create";
    }

    @RolesAllowed({"emp","guest"})
    public String read() {
    return "read";
    }

    @RolesAllowed("emp")
    public String update() {
    return "update";
    }

    @RolesAllowed("emp")
    public String delete() {
    return "delete";
    }

    }
    ejb/SecureEJB.java
    • The declaredRoles and RolesAllowed annotations take a string array as a parameter.
  4. Deployment descriptor:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
    <sun-ejb-jar>
    <security-role-mapping>
    <role-name>guest</role-name>
    <group-name>guest</group-name>
    </security-role-mapping>

    <security-role-mapping>
    <role-name>emp</role-name>
    <group-name>employee</group-name>
    </security-role-mapping>

    <enterprise-beans>
    <unique-id>0</unique-id>
    <ejb>
    <ejb-name>SecureEJB</ejb-name>
    <jndi-name>ejb/secureEJB</jndi-name>
    <gen-classes />
    </ejb>
    </enterprise-beans>
    </sun-ejb-jar>
    META-INF/sun-ejb-jar.xml

The Web Client
For a little bit more detail explanation on the Web Application, see the previous post Securing Java EE 5 Web Applications
  1. The EJB Client Jar file: When you deploy the EJB application in Glassfish, it creates a corresponding EJB Client jar file for the EJB component, which can be used in the clients. The file will created in the following directory.
    GLASSFISH_HOME\domains\DOMAIN_NAME/generated\xml/j2ee-modules/APPLICATION_NAME
  2. Selection page
    <html>
    <body>
    <h1>Home Page</h1>
    Anyone can view this page.

    <form action="securityServlet"><select name="method">
    <option value="create">create</option>
    <option value="read">read</option>
    <option value="update">update</option>
    <option value="delete">delete</option>
    </select> <input type="submit" name="submit" /></form>
    </body>
    </html>
    index.jsp
  3. Servlet
    package servlets;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.annotation.security.DeclareRoles;
    import javax.ejb.EJB;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import ejb.DABean;

    @DeclareRoles("emp")
    public class SecurityServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    @EJB(name = "timerBean", mappedName = "corbaname:iiop:localhost:3700#ejb/secureEJB")
    private DABean daBean;

    public SecurityServlet() {
    super();
    }

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    String method = request.getParameter("method");
    try {
    String result = "";
    if (method.equals("create")) {
    result = daBean.create();
    }
    if (method.equals("read")) {
    result = daBean.read();
    }

    if (method.equals("update")) {
    result = daBean.update();
    }

    if (method.equals("delete")) {
    result = daBean.delete();
    }

    out.println(request.getUserPrincipal() + " is an Authorized User");
    } catch (Exception e) {
    e.printStackTrace();
    out.println(request.getUserPrincipal() + " is not an Authorized to see this page.");
    }
    }
    }
    SecurityServlet.java
  4. Deployment descriptor
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>Java5Security</display-name>

    <servlet>
    <description></description>
    <display-name>SecurityServlet</display-name>
    <servlet-name>SecurityServlet</servlet-name>
    <servlet-class>servlets.SecurityServlet</servlet-class>
    <security-role-ref>
    <role-name>emp</role-name>
    <role-link>emp</role-link>
    </security-role-ref>
    </servlet>
    <servlet-mapping>
    <servlet-name>SecurityServlet</servlet-name>
    <url-pattern>/securityServlet</url-pattern>
    </servlet-mapping>


    <login-config>
    <auth-method>FORM</auth-method>
    <realm-name>file</realm-name>
    <form-login-config>
    <form-login-page>/login.jsp</form-login-page>
    <form-error-page>/error.jsp</form-error-page>
    </form-login-config>
    </login-config>

    <security-constraint>
    <web-resource-collection>
    <web-resource-name>Protected Area</web-resource-name>
    <url-pattern>/*</url-pattern>
    <http-method>PUT</http-method>
    <http-method>DELETE</http-method>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
    <role-name>guest</role-name>
    <role-name>emp</role-name>
    </auth-constraint>
    </security-constraint>

    <security-constraint>
    <web-resource-collection>
    <web-resource-name>Protected Area</web-resource-name>
    <url-pattern>/secure/*</url-pattern>
    <http-method>PUT</http-method>
    <http-method>DELETE</http-method>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
    <role-name>emp</role-name>
    </auth-constraint>
    </security-constraint>
    <!-- Security roles referenced by this web application -->
    <security-role>
    <role-name>guest</role-name>
    </security-role>
    <security-role>
    <role-name>emp</role-name>
    </security-role>

    <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    </web-app>
    web.xml
  5. Glassfish Deployment descriptor
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
    <sun-web-app>
    <context-root>/Java5Security</context-root>
    <security-role-mapping>
    <role-name>guest</role-name>
    <group-name>guest</group-name>
    </security-role-mapping>
    <security-role-mapping>
    <role-name>emp</role-name>
    <group-name>employee</group-name>

    </security-role-mapping>
    </sun-web-app>
    sun-web.xml
Environment: This example was run on Glassfish V2 Build 41 (Glassfish V2 Beta 2).

Tuesday, May 01, 2007

Java EE 5 on WebSphere

While the next version of WAS (v7.0) with Java EE 5, is yet to be released, you can now test some of the features such as EJB 3.0 with WebSphere software early programs. The new features are available as feature packs for the current WebSphere Application Server (v6.1).

Monday, March 12, 2007

Message Driven Bean in Java EE 5 : Part 2

In a previous post, I described how to implement Messaging in Java EE 5 using annotation. This post is an extension of that post to describe how to implement Messaging in Java EE 5 using a deployment descriptor. To implement this, you can use the same client that was described in the other post. The only change needed is in the MDB part. Here's how to implement a Message Driven bean using the deployment descriptor.
  1. Create the Message driven bean: The message driven bean here is a simple Java class that implements the MessageListener interface. All the configuration will be done in the deployment descriptors.
    package jms;

    import javax.jms.JMSException;
    import javax.jms.Message;
    import javax.jms.MessageListener;
    import javax.jms.TextMessage;

    import org.apache.log4j.Level;
    import org.apache.log4j.Logger;

    public class Messaging3Mdb implements MessageListener {

    static final Logger logger = Logger.getLogger("MDB");

    public Messaging3Mdb() {
    }

    public void onMessage(Message inMessage) {
    TextMessage msg = null;
    logger.setLevel(Level.ALL);

    try {
    if (inMessage instanceof TextMessage) {
    msg = (TextMessage) inMessage;
    logger.info("MESSAGE BEAN: Message received: " + msg.getText());
    } else {
    logger.warn("Message of wrong type: " + inMessage.getClass().getName());
    }
    } catch (JMSException e) {
    logger.error("MessageBean.onMessage: JMSException: " + e.toString());
    } catch (Throwable te) {
    logger.error("MessageBean.onMessage: Exception: " + te.toString());
    }
    }
    }
    Messaging3Mdb.java
  2. The sun-ejb-jar.xml file: This file contains the mapping of the JMS resources.
    <?xml version="1.0" encoding="UTF-8"?>
    <sun-ejb-jar>
    <enterprise-beans>
    <name>Ejb3DD</name>
    <ejb>
    <ejb-name>Messaging3Mdb</ejb-name>
    <jndi-name>jms/testQueue</jndi-name>
    <mdb-connection-factory>
    <jndi-name>jms/connectionFactory</jndi-name>
    </mdb-connection-factory>
    </ejb>
    </enterprise-beans>
    </sun-ejb-jar>
    META-INF/sun-ejb-jar.xml
  • The EJB deployment descriptor:
    <?xml version="1.0" encoding="UTF-8" ?>
    <ejb-jar>
    <enterprise-beans>
    <message-driven>
    <ejb-name>Messaging3Mdb</ejb-name>
    <ejb-class>jms.Messaging3Mdb</ejb-class>
    <messaging-type>javax.jms.MessageListener</messaging-type>
    <message-destination-type>javax.jms.Queue</message-destination-type>

    </message-driven>
    </enterprise-beans>
    </ejb-jar>
    META-INF/ejb-jar.xml

  • Environment: This example was implemented on Glassfish v1, Milestone 7
  • Wednesday, February 28, 2007

    Java EE best practices

    A recent article in IBM developerworks discusses best practices in Java EE development. This is an update of the 2004 article on J2EE best practices. Here's the complete list:
    1. Always use MVC.
    2. Don't reinvent the wheel.
    3. Apply automated unit tests and test harnesses at every layer.
    4. Develop to the specifications, not the application server.
    5. Plan for using Java EE security from Day One.
    6. Build what you know.
    7. Always use session facades whenever you use EJB components.
    8. Use stateless session beans instead of stateful session beans.
    9. Use container-managed transactions.
    10. Prefer JSPs as your first choice of presentation technology.
    11. When using HttpSessions, store only as much state as you need for the current business transaction and no more.
    12. Take advantage of application server features that do not require your code to be modified.
    13. Play nice within existing environments.
    14. Embrace the qualities of service provided by the application server environment.
    15. Embrace Java EE, don't fake it.
    16. Plan for version updates.
    17. At all points of interest in your code, log your program state using a standard logging framework.
    18. Always clean up after yourself.
    19. Follow rigorous procedures for development and testing.
    Links
    1. Top Java EE Best Practices
    2. The top 10 (more or less) J2EE best practices

    Thursday, January 18, 2007

    EJB 3 Timer Service

    Applications with business processes that are dependent on periodic notifications (for state transitions etc.) need a timer/scheduler service. In the past I posted how to use the Quartz Scheduler for scheduling jobs. In this post, I will describe the use of the EJB 3 Timer Service for scheduling, or temporal event driven processing.

    The EJB Timer Service is a container-managed service that provides a way to allow methods to be invoked at specific times or time intervals. The EJB Timer may be set to invoke certain EJB methods at a specific time, after a specific duration, or at specific recurring intervals. The Timer Service is implemented by the EJB container and injected into the EJB through the EJBContext interface, or the EJB can access it through a JNDI lookup. In the example presented below, the EJB timer is set when the client invokes the startTimer method. The checkStatus() method is used to get the time left for the next timeout. The example was implemented on Glassfish server, with Eclipse 3.2 used for development.
    Follow these steps to implement the example.

    The EJB
    1. The EJB interface: The interface for the EJB is shown below.
      package ejb;

      public interface ITimedBean {
      public String checkStatus();
      public void startTimer();
      }
      ITimedBean.java
    2. The Bean: The following is the code for the EJB followed by a brief explanation
      package ejb;

      import java.util.Collection;
      import java.util.Iterator;

      import javax.annotation.Resource;
      import javax.ejb.Remote;
      import javax.ejb.SessionContext;
      import javax.ejb.Stateless;
      import javax.ejb.Timeout;
      import javax.ejb.Timer;

      @Stateless(mappedName="ejb/timedBean")
      @Remote
      public class TimedBean implements ITimedBean {

      @Resource
      private SessionContext ctx;

      public void startTimer() {
      ctx.getTimerService().createTimer(1000, 1000, null);
      System.out.println("Timers set");

      }

      public String checkStatus() {
      Timer timer = null;
      Collection timers = ctx.getTimerService().getTimers();
      Iterator iter = timers.iterator();
      while (iter.hasNext()) {
      timer = (Timer) iter.next();

      return ("Timer will expire after " + timer.getTimeRemaining() + " milliseconds.");
      }
      return ("No timer found");

      }

      @Timeout
      public void handleTimeout(Timer timer) {
      System.out.println("HandleTimeout called.");

      }
      }
      TimedBean.java
      • The @Stateless(mappedName="ejb/timedBean") annotation declares the bean as a stateless EJB. The mappedName attribute defines the global JNDI name to which this EJB will be bound.
      • In the startTimer method, the ctx.getTimerService().createTimer(1000, 1000, null); call is used to create the timer, this call will create a timer that invokes the methods at specific intervals. Another way to create a timer would be to use the call ctx.getTimerService().createTimer(1000, null);, in which case, the timer will invoke the EJB method just once.
      • The EJB 3 Timer Service also allows you to send client-specific information at timer creation, throught the public Timer createTimer(long initialDuration, long intervalDuration, java.io.Serializable info); and some overloaded methods as shown below in the TimerService interface.
        public interface javax.ejb.TimerService {

        public Timer createTimer(long duration,java.io.Serializable info);

        public Timer createTimer(long initialDuration,long intervalDuration, java.io.Serializable info);

        public Timer createTimer(java.util.Date expiration,java.io.Serializable info);

        public Timer createTimer(java.util.Date initialExpiration,long intervalDuration, java.io.Serializable info);

        public Collection getTimers();
        }
      • A timer may be cancelled at any time, by using the cancel() method in the Timer interface.
      • The @Timeout annotation declares the handleTimeout() method to be a callback method for the timer.
    3. Deploying: When deploying on Glassfish using the Admin console, check the "Generate RMI Stubs in a Jar File" option. The Jar file will be created in the GLASSFISH_HOME/domains/DOMAIN_NAME/generated/xml/j2ee-modules/APPLICATION_NAME directory.

    The Timer Client

    For this example, I used a web client. The client has a context listener which loads the timer when the application is deployed. A single servlet is used to invoke the checkStatus() method on the client.
    1. Start with a Dynamic Web Application in Eclipse. Include the generated client Jar file as a dependency.
    2. The Context Listener: The code for the context listener is shown below.
      package servlets;

      import javax.ejb.EJB;
      import javax.servlet.ServletContextEvent;
      import javax.servlet.ServletContextListener;

      import ejb.ITimedBean;

      public class LoadTimer implements ServletContextListener {
      @EJB(name="timerBean", mappedName="corbaname:iiop:localhost:3700#ejb/timedBean")
      private ITimedBean timerBean;

      public void contextInitialized(ServletContextEvent servletcontextevent) {
      System.out.println("Starting timer");
      timerBean.startTimer();
      }

      public void contextDestroyed(ServletContextEvent servletcontextevent) {

      }

      public ITimedBean getTimerBean() {
      return timerBean;
      }

      public void setTimerBean(ITimedBean timerBean) {
      this.timerBean = timerBean;
      }

      }
      LoadTimer.java

      You will notice that the Context listener has a timerBean field with @EJB annotation. The mapped name for the EJB is defined to be the full JNDI name.
      @EJB(name="timerBean", mappedName="corbaname:iiop:localhost:3700#ejb/timedBean")
      This is only needed in case of remote deployments on different clusters. In the same cluster you could simply use "ejb/timedBean".
    3. The Servlet: The servlet is has a similar @EJB annotation.
      package servlets;

      import java.io.IOException;

      import javax.ejb.EJB;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      import ejb.ITimedBean;

      public class TimerClient extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
      @EJB(name="timerBean", mappedName="corbaname:iiop:localhost:3700#ejb/timedBean")
      private ITimedBean timerBean;

      protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      response.getWriter().println(timerBean.checkStatus());
      response.getWriter().println(timerBean.checkStatus());
      response.getWriter().println(timerBean.checkStatus());

      }

      public ITimedBean getTimerBean() {
      return timerBean;
      }

      public void setTimerBean(ITimedBean timerBean) {
      this.timerBean = timerBean;
      }
      }
      TimerClient.java
    4. The Deployment descriptor: The deployment descriptor is listed below.
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>TimerClientWeb</display-name>
      <listener>
      <listener-class>servlets.LoadTimer</listener-class>
      </listener>
      <servlet>
      <description></description>
      <display-name>TimerClient</display-name>
      <servlet-name>TimerClient</servlet-name>
      <servlet-class>servlets.TimerClient</servlet-class>
      </servlet>

      <servlet-mapping>
      <servlet-name>TimerClient</servlet-name>
      <url-pattern>/timerClient</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
      <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
      web.xml

    Timer Service Additional Info (From the EJB 3.0 Specification)
    • Invocations of the methods to create and cancel timers and of the timeout callback method are typically made within a transaction.
    • If the transaction is rolled back, the timer creation is rolled back and so is the case with timer cancellation.
    • If container-managed transaction demarcation is used and the REQUIRED or REQUIRES_NEW transaction attribute is specified or defaulted (Required or RequiresNew if the deployment descriptor is used), the container must begin a new transaction prior to invoking the timeout callback method.
    • If the transaction fails or is rolled back, the container must retry the timeout at least once.
    • Timers survive container crashes, server shutdown, and the activation/passivation and load/store cycles of the enterprise beans that are registered with them.
    • Since the timeout callback method is an internal method of the bean class, it has no client security context. When getCallerPrincipal is called from within the timeout callback method, it returns the container's representation of the unauthenticated identity.

    Wednesday, January 17, 2007

    Securing Java EE 5 Web Applications

    In this post I will give a brief overview of securing web applications in Java EE 5 with the help of a simple example. The example application consists of a Servlet (securityServlet) and two pages (index.jsp and secure/index.jsp). Two users (newemployee and newguest) with roles employee and guest, will be created, with the following permissions
    1. The "guest" user will have access to index.jsp
    2. The "employee" user will have access to secure/index.jsp.
    3. Both users have access to the servlet.
    This example was developed on Eclipse and run on Glassfish application server. Follow these steps to implement the example

    Create Users in Glassfish
    1. Go to Configuration->Security->Realms->file in the Glassfish admin console.
    2. In the file realm, click on manage users.
    3. Add new users by clicking on add there.
    The Web Application
    1. The Web Deployment Descriptor: The following listing shows the complete deployment descriptor used for this example, followed by a quick explanation.
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>Java5Security</display-name>

      <servlet>
      <description></description>
      <display-name>SecurityServlet</display-name>
      <servlet-name>SecurityServlet</servlet-name>
      <servlet-class>servlets.SecurityServlet</servlet-class>
      <security-role-ref>
      <role-name>emp</role-name>
      <role-link>employee</role-link>
      </security-role-ref>
      </servlet>
      <servlet-mapping>
      <servlet-name>SecurityServlet</servlet-name>
      <url-pattern>/securityServlet</url-pattern>
      </servlet-mapping>

      <login-config>
      <auth-method>FORM</auth-method>
      <realm-name>file</realm-name>
      <form-login-config>
      <form-login-page>/login.jsp</form-login-page>
      <form-error-page>/error.jsp</form-error-page>
      </form-login-config>
      </login-config>

      <security-constraint>
      <web-resource-collection>
      <web-resource-name>Protected Area</web-resource-name>
      <url-pattern>/*</url-pattern>
      <http-method>PUT</http-method>
      <http-method>DELETE</http-method>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
      <role-name>guest</role-name>
      <role-name>employee</role-name>
      </auth-constraint>
      </security-constraint>

      <security-constraint>
      <web-resource-collection>
      <web-resource-name>Protected Area</web-resource-name>
      <url-pattern>/secure/*</url-pattern>
      <http-method>PUT</http-method>
      <http-method>DELETE</http-method>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
      <role-name>employee</role-name>
      </auth-constraint>
      </security-constraint>
      <!-- Security roles referenced by this web application -->
      <security-role>
      <role-name>guest</role-name>
      </security-role>
      <security-role>
      <role-name>employee</role-name>
      </security-role>

      <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      </welcome-file-list>
      </web-app>
      WEB-INF/web.xml
      • In the servlet declaration, the <security-role-ref> element maps the rolename used in the servlet to role declared in the deployment descritpor (this is needed only when the role declared in the deployment descriptor is different from the role used in the servlet (employee and emp)).
      • In the login-config, the <realm-name> element is used to declare the realm in which authentication takes place
      • Realms: A realm is a database of users and groups that identify valid users of a Web application and are controlled by the same authentication policy. Three realms, file, admin-realm, and certificate realms come preconfigured in Glassfish Application Server. For this example I use the file realm, where the user credentials are stored locally in a file.
    2. Mapping Roles to Users/Groups in Security Realm: In order to map the roles used in the application to the users defined in the security realm, you have to add the role mappings in the WEB-INF/sun-web.xml. The file is shown below.
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <context-root>/Java5Security</context-root>
      <security-role-mapping>
      <role-name>guest</role-name>
      <principal-name>newguest</principal-name>
      </security-role-mapping>
      <security-role-mapping>
      <role-name>employee</role-name>
      <principal-name>newemployee</principal-name>
      </security-role-mapping>
      </sun-web-app>
      WEB-INF/sun-web.xml
    3. The Servlet: The following is a listing of the servlet used for this example
      package servlets;

      import java.io.IOException;
      import java.io.PrintWriter;

      import javax.annotation.security.DeclareRoles;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      @DeclareRoles("emp")
      public class SecurityServlet extends javax.servlet.http.HttpServlet implements
      javax.servlet.Servlet {

      public SecurityServlet() {
      super();
      }

      protected void service(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
      PrintWriter out = response.getWriter();
      if (request.isUserInRole("emp"))

      out.println(request.getUserPrincipal() + " is an Authorized User");
      else
      out.println(request.getUserPrincipal() + " is not an Authorized to see this page.");
      }
      }
      SecurityServlet.java
      • The @DeclareRoles annotation is used to define the security roles in the application. This annotation is specified on a class, and it typically would be used to define roles that could be tested (i.e., by calling isUserInRole) from within the methods of the annotated class.
      • The isUserInRole() method is from J2EE.
    4. The login page: The following is the listing for the login.jsp page. There is nothing new here.
      <%@ taglib prefix='c' uri='http://java.sun.com/jstl/core'%>
      <html>
      <head>
      <title>Login</title>
      </head>

      <body>
      <h1>Login</h1>

      <h2>Hello, please login:</h2>
      <br>
      <br>
      <form action="j_security_check" method=post>
      <table>
      <tr>
      <td>User:</td>
      <td><input type="text" name="j_username" size="25"></td>
      </tr>
      <tr>
      <td>Password:</td>
      <td><input type='password' name='j_password'></td>
      </tr>

      <tr>
      <td colspan='2'><input name="submit" type="submit"></td>
      </tr>
      <tr>
      <td colspan='2'><input name="reset" type="reset"></td>
      </tr>
      </table>

      </form>
      </body>
      </html>
      /login.jsp
    5. The index.jsp and error.jsp could be any JSP page
    6. This post did not describe how to logout. But that has been discussed earlier in the Form-based Authentication Logout post.

    Wednesday, December 27, 2006

    Data Access with Spring and JPA

    The JDBC abstraction layer of Spring framework offers an understandable exception hierarchy, simplifies error handling, and greatly reduces the amount of code you'll need to write. Spring 2.0 has support for using JPA in the Data Access Layer. In this post, I will describe a step-by-step approach to implementing a Web Application that uses Spring 2.0 and Java Persistence API for Data Access. The example is the same one that I used in the previous persistence examples. This example is implemented using Spring 2.0 on Glassfish.
    1. The Entity Class: The Entity class is the Employee class shown below:
      package beans;

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

      @Entity
      @Table(name = "EMP")
      public class Employee {

      private long empId;

      private String empName;

      private String empJob;

      private long empSal;

      @Id
      @Column(name = "EMPNO")
      public long getEmpId() {
      return empId;
      }

      public void setEmpId(long empId) {
      this.empId = empId;
      }

      @Column(name = "JOB")
      public String getEmpJob() {
      return empJob;
      }

      public void setEmpJob(String empJob) {
      this.empJob = empJob;
      }

      @Column(name = "ENAME")
      public String getEmpName() {
      return empName;
      }

      public void setEmpName(String empName) {
      this.empName = empName;
      }

      @Column(name = "EMPSAL")
      public long getEmpSal() {
      return empSal;
      }

      public void setEmpSal(long empSal) {
      this.empSal = empSal;
      }
      }
      Employee.java
    2. The JSP page: The JSP page is also the same as used previously and is shown below.
      <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
      <jsp:directive.page contentType="text/html; charset=UTF-8" />
      <jsp:directive.page
      import="org.springframework.web.context.support.XmlWebApplicationContext,org.springframework.beans.BeanUtils,org.springframework.web.context.ConfigurableWebApplicationContext, org.springframework.beans.factory.BeanFactory, data.DAO" />
      <link rel="stylesheet" type="text/css" href="css/screen.css" />
      <jsp:scriptlet>
      int pageNumber=1;
      if(request.getParameter("page") != null) {
      session.setAttribute("page", request.getParameter("page"));
      pageNumber = Integer.parseInt(request.getParameter("page"));
      } else {
      session.setAttribute("page", "1");
      }
      String nextPage = (pageNumber +1) + "";
      ConfigurableWebApplicationContext wac =
      (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(XmlWebApplicationContext.class);
      wac.setServletContext(this.getServletContext());
      wac.refresh();
      session.setAttribute( "EmpList", ((DAO)wac.getBean("dao")).getData(pageNumber));
      System.out.println(((java.util.List)session.getAttribute("EmpList")).size());
      String myUrl = "pagingEmp.jsp?page=" + nextPage;
      System.out.println(myUrl);

      pageContext.setAttribute("myUrl", myUrl);
      </jsp:scriptlet>
      <h2 align="center">Emp Table with Display tag</h2>
      <jsp:useBean id="EmpList" scope="session" type="java.util.List"></jsp:useBean>
      <table>
      <tr>
      <th>Employee Id</th>
      <th>Name</th>
      <th>Job</th>
      <th>Salary</th>
      </tr>
      <c:forEach items="${EmpList}" var="emp" begin="0" end="10">
      <tr>
      <td><c:out value="${emp.empId}"></c:out></td>
      <td><c:out value="${emp.empName}"></c:out></td>
      <td><c:out value="${emp.empJob}"></c:out></td>
      <td><c:out value="${emp.empSal}"></c:out></td>
      </tr>
      </c:forEach>

      <tr>
      <td colspan="2"></td>
      <td colspan="2"><a href="${pageScope.myUrl}">nextPage</a></td>
      </tr>
      </table>
      </jsp:root>
      pagingEmp.jsp
    3. The Application Context: The application context is shown below:
      <?xml version="1.0" encoding="UTF-8"?>
      <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.xsd">
      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value ="oracle.jdbc.driver.OracleDriver" />
      <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl" />
      <property name="username" value="scott" />
      <property name="password" value="tiger" />
      </bean>
      <bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="persistenceUnitName" value="myPersistenceUnit" />

      <property name="dataSource" ref="dataSource" />
      <property name="loadTimeWeaver">
      <bean class="org.springframework.instrument.classloading.glassfish.GlassFishLoadTimeWeaver"/>
      </property>
      <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaDialect" />
      </property>
      <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
      <property name="showSql" value="true" />
      <property name="generateDdl" value="false" />
      <property name="databasePlatform" value="oracle.toplink.essentials.platform.database.oracle.OraclePlatform" />
      </bean>
      </property>
      </bean>

      <bean id="dao" class="data.DAO">
      <property name="entityManagerFactory" ref="entityManagerFactory" />
      </bean>
      </beans>
      WEB-INF/applicationContext.xml
    4. The Data Access Object: The data access object extends the JpaDaoSupport. JpaDaoSupport like JdbcTemplate implements most of the boiler-plate code for implementing JPA data access.
      package data;

      import java.util.List;

      import org.springframework.orm.jpa.JpaTemplate;
      import org.springframework.orm.jpa.support.JpaDaoSupport;

      public class DAO extends JpaDaoSupport {
      public long empId;
      public String empName;
      public String empJob;
      public long empSal;

      public List getData(long minSal) {
      JpaTemplate daoTmplt = getJpaTemplate();
      System.out.println("Creating query.");
      List result = null;
      try {
      result = daoTmplt.find("select e from Employee e");
      }catch(Throwable e) {
      e.printStackTrace();
      }
      return result;
      }
      }
      DAO.java
    5. The persistence xml: The persistence XML file does not have any persistence description as used in the JPA post. This is because it is defined in the application context XML file.
      <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
      <persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL"></persistence-unit>
      </persistence>
      src/META-INF/persistence.xml
    6. The Web Deployment Descritor: The web deployment descriptor is shown below. Note the listener definition for org.springframework.web.context.ContextLoaderListener.
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>SpringJpa</display-name>
      <context-param>
      <param-name>log4jConfigLocation</param-name>
      <param-value>/WEB-INF/log4j.xml</param-value>
      </context-param>
      <listener>
      <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
      </listener>

      <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <welcome-file-list>
      <welcome-file>index.html</welcome-file>
      <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
      web.xml
    7. Setup: In order to run the example on Glassfish, you have to create an EAR and install the EAR instead of trying to deploy a WAR file on Glassfish. Deploying WAR files gives some classloading related exceptions. The reason is, as yet, unknown to me. Hope to find out soon.

    Thursday, December 21, 2006

    Message Driven Bean in Java EE 5

    In the past, I posted a few examples of implementing Messaging using J2EE and Spring. In this post, I will give an example of how to implement Message Driven beans using Java EE 5. I used Eclipse 3.2 and Glassfish for this example. Follow these steps to run the example:
    1. Download and Install Glassfish: You can download the latest build of Glassfish from the Glassfish Download site. To install follow these steps
      1. In the download directory, run the following command
        java -Xmx256m -jar glassfish-installer-version-build.jar
      2. The previous command will create a directory by the name glassfish. Go to the glassfish directory and run this command
        ant -f setup-cluster.xml
      3. The admin console for the default installation will be at http://localhost:4848/asadmin, and the default username and password are "admin" and "adminadmin" respectively.
    2. Download and Install the Glassfish Plugin for Eclipse from here.
    3. Create a Glassfish Server in Eclipse: (For some reason, Eclipse did not detect the Server Runtime without creating a Server, we'll worry about that later)
    4. Creating the EJB 3 Message Driven Bean:
      1. Create a "Java project" in Eclipse.
      2. Add the Glassfish runtime library as a dependency for the project.
      3. The following is the code for the Message Driven Bean that I used for the Example. This is in the jms package of the Java project.
        package jms;

        import javax.annotation.Resource;
        import javax.ejb.MessageDriven;
        import javax.ejb.MessageDrivenContext;
        import javax.jms.JMSException;
        import javax.jms.Message;
        import javax.jms.MessageListener;
        import javax.jms.TextMessage;

        @MessageDriven(mappedName = "jms/testQueue")
        public class Messaging3Mdb implements MessageListener {

        @Resource
        private MessageDrivenContext mdc;

        public Messaging3Mdb() {
        }
        public void onMessage(Message inMessage) {
        TextMessage msg = null;
        try {
        msg = (TextMessage) inMessage;
        System.out.println("Message received : " + msg.getText());
        } catch (JMSException e) {
        e.printStackTrace();
        mdc.setRollbackOnly();
        }
        }
        }
        Messaging3Mdb.java
    5. Creating the Client: I used a Servlet for the client, so that I could also use JMS resource injection. To create the Client
      1. Create a "Dynamic Web Project" in Eclipse.
      2. Change the Web.xml file to Reflect Java EE 5 descriptor, as shown below
        <?xml version="1.0" encoding="UTF-8"?>
        <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <display-name>Messaging3Web</display-name>
        <servlet>
        <description></description>
        <display-name>MessagingClient</display-name>
        <servlet-name>MessagingClient</servlet-name>
        <servlet-class>servlets.MessagingClient</servlet-class>
        </servlet>
        <servlet-mapping>
        <servlet-name>MessagingClient</servlet-name>
        <url-pattern>/MessagingClient</url-pattern>
        </servlet-mapping>
        <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
        </web-app>
        web.xml
      3. This is the code for the Servlet that acts as a client to the MDB created above
        package servlets;

        import java.io.IOException;

        import javax.annotation.Resource;
        import javax.jms.Connection;
        import javax.jms.ConnectionFactory;
        import javax.jms.Destination;
        import javax.jms.JMSException;
        import javax.jms.MessageProducer;
        import javax.jms.Queue;
        import javax.jms.Session;
        import javax.jms.TextMessage;
        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        public class MessagingClient extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

        @Resource(mappedName = "jms/testQueue")
        private Queue queue;

        @Resource(mappedName = "jms/connectionFactory")
        private ConnectionFactory jmsConnectionFactory;

        public MessagingClient() {
        super();
        }

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

        }

        public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Connection connection = null;
        Destination dest = (Destination) queue;
        try {
        connection = jmsConnectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        MessageProducer producer = session.createProducer(dest);
        TextMessage message = session.createTextMessage();

        message.setText("Hello");
        response.getOutputStream().println("Sending message: " + message.getText());
        System.out.println("Sending message: " + message.getText());
        producer.send(message);

        producer.send(session.createMessage());
        } catch (JMSException e) {
        e.printStackTrace();
        } finally {
        if (connection != null) {
        try {
        connection.close();
        } catch (JMSException e) {
        }
        }
        }
        }
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        }
        }
        MessagingClient.java
    6. Create the JMS Connection Factory and Queue: The connection factory and the queue can be created using the admin console or from the command line. The admin console is quite easy, you just have to go to the Resources->JMS Resources->Connection Factories and Resources->JMS Resources->Destination Resources. From the command line you have to use the following two commands from the GLASSFIS_HOME/bin directory.
      asadmin create-jms-resource --user admin --restype javax.jms.Queue --property imqDestinationName=testQueue jms/testQueue
      asadmin create-jms-resource --user admin --restype javax.jms.ConnectionFactory --property imqDestinationName=connectionFactory jms/connectionFactory
    7. Deploy the MDB: Since we created a Java Project, eclipse does not allow you to install from the IDE, so you have to export the Java jar file and use the admin console to deploy. Deploy it as an "EJB Module".
    8. Deploy the Client as a Web application

    Tuesday, December 19, 2006

    Data Access with Java Persistence API

    The Java Persistence API simplifies the entity persistence model and adds new capabilities to the Java EE platform technology, it is the standard API for the management of persistence and object/relational mapping in Java EE 5. In this post, I will give a simple example of how to use JPA from a web application. I used BEA Kodo 4.1 and Weblogic application server 10.0 techinical preview. Follow these steps to run the example
    1. Download BEA Kodo 4.1 from here. You will also need to have a license file to use Kodo. The license file can be downloaded from here. Copy the license file into your classpath.

    2. You can download the Weblogic Application Server 10 TP from BEA.
    Example Code
    1. Start with a "Dynamic Web Project" in Eclipse.
    2. Create the Persistence Class (Entity): The source code for the entity class is shown below:
      package beans;
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.Id;
      import javax.persistence.Table;

      @Entity
      @Table(name = "EMP")
      public class Employee {

      private long empId;

      private String empName;

      private String empJob;

      private long empSal;

      @Id
      @Column(name = "EMPNO")
      public long getEmpId() {
      return empId;
      }

      public void setEmpId(long empId) {
      this.empId = empId;
      }

      @Column(name = "JOB")
      public String getEmpJob() {
      return empJob;
      }

      public void setEmpJob(String empJob) {
      this.empJob = empJob;
      }

      @Column(name = "ENAME")
      public String getEmpName() {
      return empName;
      }

      public void setEmpName(String empName) {
      this.empName = empName;
      }

      @Column(name = "EMPSAL")
      public long getEmpSal() {
      return empSal;
      }

      public void setEmpSal(long empSal) {
      this.empSal = empSal;
      }
      }
      Employee.java
      • The persistence classes, or entities are annotated with the javax.persistence.Entity annotation.
      • It is required to have a public/protected no-arg constructor.
      • Neither Entity class nor any of it's properties are to be declared final.
      • The @Id annotation defines a particular field as a primary key.
      • The properties of the Entity class are mapped to the Columns of the database with the @Column annotation.
    3. Create the Data Access Object: The code for the Data access object is shown below
      public class DAO {
      private static int pageSize = 3;
      private EntityManagerFactory emf;

      private static DAO dao = new DAO();
      private DAO() {
      }
      public static DAO getInstance() {
      return dao;
      }

      public List getData(int pageNumber) {

      EntityManager em = null;
      try {
      System.out.println(emf);
      em = emf.createEntityManager();

      Query query = em.createQuery("SELECT e FROM Employee e");
      query = query.setFirstResult(pageSize * (pageNumber - 1));
      query.setMaxResults(pageSize);
      List results = query.getResultList();
      return results;

      } catch (Exception ex) {
      ex.printStackTrace();
      return null;
      } finally {
      em.close();
      }

      }

      public void setEmf(EntityManagerFactory emf) {
      dao.emf = emf;
      }
      }
      DAO.java
      • The DAO class uses the EntityManagerFactory injected by the ContextListener on initialization, to obtain an instance of the EntityManager which is used to create Queries.
    4. Create a Context Listener: JPA annotations can be used to inject the EntityManager and the EntityManagerFactory into the Managed objects. The persistence annotations are supported only with managed classes such as servlet, filters, listeners, etc. You cannot use annotations with regular POJOs. To that end, I have created a Context Listener, which will be injected with the and which inturn injects the EntityManagerFactoryEntityManagerFactory into the DAO class.
      public class ContextListener implements ServletContextListener {

      @PersistenceUnit(unitName="emp")
      EntityManagerFactory emf;

      public void contextDestroyed(ServletContextEvent arg0) {
      }
      public void contextInitialized(ServletContextEvent arg0) {
      // EntityManagerFactory emf = Persistence.createEntityManagerFactory ("emp");
      DAO dao = DAO.getInstance();
      System.out.println("EMF : " + emf);
      dao.setEmf(emf);
      }
      }
      ContextListener.java

      The commented out line in the ContextListener class shown below
      EntityManagerFactory emf = Persistence.createEntityManagerFactory ("emp");
      is another way to obtain an instance of the EntityManagerFactory.

    5. Update Web.xml: By default, when you create a "dynamic web project" in eclipse as of today, the web.xml file will be prepared for J2EE 1.4, you have to update it to Java EE5 (note the web-app declaration below). The application server will not inject the EntityManagerFactory into the ContextListener if the Web-App version is not set to 2.5, and you will get a NullPointerException. You also have to add the ContextListener to the web.xml file.
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee"
      version="2.5"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <display-name>JPATest</display-name>
      <listener>
      <listener-class>listeners.ContextListener</listener-class>
      </listener>
      <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      </web-app>
      web.xml
    6. Create the JSP file: The JSP file here is similar to the previous JSP files used for the Paging examples. The only difference being the use of the DAO.getInstance() method. This change was made to be able to inject the EntityManagerFactory into the DAO object.
      <jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:c="urn:jsptld:http://java.sun.com/jsp/jstl/core">
      <jsp:directive.page contentType="text/html; charset=UTF-8" />

      <link rel="stylesheet" type="text/css" href="css/screen.css" />
      <jsp:scriptlet>
      int pageNumber=1;
      if(request.getParameter("page") != null) {
      session.setAttribute("page", request.getParameter("page"));
      pageNumber = Integer.parseInt(request.getParameter("page"));
      } else {
      session.setAttribute("page", "1");
      }
      String nextPage = (pageNumber +1) + "";
      session.setAttribute( "EmpList", data.DAO.getInstance().getData(pageNumber));
      System.out.println(((java.util.List)session.getAttribute("EmpList")).size());
      String myUrl = "pagingEmp.jsp?page=" + nextPage;
      System.out.println(myUrl);

      pageContext.setAttribute("myUrl", myUrl);
      </jsp:scriptlet>
      <h2 align="center">Emp Table with Display tag</h2>
      <jsp:useBean id="EmpList" scope="session" type="java.util.List"></jsp:useBean>
      <table>
      <tr>
      <th>Employee Id</th>
      <th>Name</th>
      <th>Job</th>
      <th>Salary</th>
      </tr>
      <c:forEach items="${EmpList}" var="emp" begin="0" end="10">
      <tr>
      <td><c:out value="${emp.empId}"></c:out></td>
      <td><c:out value="${emp.empName}"></c:out></td>
      <td><c:out value="${emp.empJob}"></c:out></td>
      <td><c:out value="${emp.empSal}"></c:out></td>
      </tr>
      </c:forEach>

      <tr>
      <td colspan="2"></td>
      <td colspan="2"><a href="${pageScope.myUrl}">nextPage</a></td>
      </tr>
      </table>
      </jsp:root>
      pagingEmp.jsp
    7. The persistence Unit definition: A persistence unit defines a set of entity classes managed by a single EntityManager. This set of entity classes represents the data contained within a single data store.
      Persistence units are defined in the persistence.xml configuration file. The persistence.xml file is to be placed in the CLASSPATH/META-INF/ directory. Here is the persistence unit I defined in the example
      <?xml version="1.0" encoding="ISO-8859-1" ?>

      <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="emp" transaction-type="JTA">
      <class>beans.Employee</class>
      <properties>
      <property name="kodo.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521/orcl" />
      <property name="kodo.ConnectionDriverName" value="oracle.jdbc.driver.OracleDriver" />
      <property name="kodo.ConnectionUserName" value="scott" />
      <property name="kodo.ConnectionPassword" value="tiger" />
      <property name="kodo.jdbc.SynchronizeMappings" value="refresh" />
      <property name="kodo.Log" value="DefaultLevel=WARN, SQL=WARN, Runtime=INFO, Tool=INFO" />
      </properties>
      </persistence-unit>

      </persistence>
      src/META-INF/persistence.xml
    8. The Jar files: Make sure that you include the following JAR files from the KODO download
      • serp.jar
      • openjpa.jar
      • ojdbc14.jar
      • kodo.jar
      • jta-spec1_0_1.jar
      • jpa.jar
      • jdo.jar
      • commons-collections-3.2.jar
      • commons-pool-1.3.jar
      • commons-lang-2.1.jar
      • jca1.0.jar
      You will also need the jar files for JSTL etc...
    Resources: This post described the implementation of JPA on Weblogic, here are a few resources that help you to implement JPA in different environments

    Popular Posts