Search This Blog

Tuesday 29 March 2011

RESTful Web Service using JPA/EJB 3.0 Entities

In this example I created a more common use case of using JAX-RS Web Service based on a JPA/EJB 3.0 entity. I will only show the code here and what the project looks like in JDeveloper but in short you would have a setup as follows based on a DEPT table in the classic SCOTT schema.

JAX-RS Web Service -> SLSB ->  JPA/EJB 3.0 entity

1. Create the DEPT JPA/EJB 3.0 Entity using the"Entities from tables" EJB wizard.
2. Create a Statelesss Session bean which generates facade methods for the JPA Entity we created at step #1

Note: In this example we will just implement the default Dept.findAll named query created from the JPA Entity

package pas.au.jaxrs.jpa.dept;

import java.util.List;

import javax.ejb.Stateless;

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

@Stateless(name = "DeptSessionEJB", mappedName = "JAX-RS-DeptJPADemo-Demo-DeptSessionEJB")
public class DeptSessionEJBBean
  implements DeptSessionEJB, DeptSessionEJBLocal
{
  @PersistenceContext(unitName="Demo")
  private EntityManager em;

  public DeptSessionEJBBean()
  {
  }

  public Object queryByRange(String jpqlStmt, int firstResult,
                             int maxResults)
  {
    Query query = em.createQuery(jpqlStmt);
    if (firstResult > 0)
    {
      query = query.setFirstResult(firstResult);
    }
    if (maxResults > 0)
    {
      query = query.setMaxResults(maxResults);
    }
    return query.getResultList();
  }

  /** <code>select o from Dept o</code> */
  public List<Dept> getDeptFindAll()
  {
    return em.createNamedQuery("Dept.findAll").getResultList();
  }
}  

3. Create the JAX-RS Web Service as follows.
package pas.au.jaxrs.jpa.dept;

import java.util.Hashtable;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;


@Path ("/deptjpaservice")
public class DeptService
{
  private DeptSessionEJB deptBean;
  
  public DeptService()
  {
    Context context;
    try
    {
      context = getInitialContext();
      deptBean = (DeptSessionEJB)
        context.lookup
         ("JAX-RS-DeptJPADemo-Demo-DeptSessionEJB#pas.au.jaxrs.jpa.dept.DeptSessionEJB");
    }
    catch (NamingException e)
    {
      throw new RuntimeException (e.getMessage());
    }
  }

  @GET
  @Path("/departments")
  @Produces(MediaType.APPLICATION_XML)
  public List<Dept> listDepartments()
  {
    return deptBean.getDeptFindAll();
  }

  private static Context getInitialContext() throws NamingException
  {
    return new InitialContext();
  }
}

You could deploy this to Weblogic 10.3.4as per a previous post. In the example client above we just rujn it in the Integrated Server from JDeveloper to test it out.

4.  Run the JAX-RS Web Service when finished you should see the following in the log file.

[01:10:31 PM] ----  Deployment finished.  ----
Run startup time: 11380 ms.
[Application JAX-RS-DeptJPADemo deployed to Server Instance IntegratedWebLogicServer]

Target Application WADL -- http://localhost:7101/jaxrs-deptjpa/jersey/application.wadl

Target URL -- http://localhost:7101/jaxrs-deptjpa/jersey/deptjpaservice/departments

5. Using curl access it from a putty client as follows.

> curl http://paslap-au.au.oracle.com:7101/jaxrs-deptjpa/jersey/deptjpaservice/departments

Of course the example above just shows how easy it is to call a JAX-RS service from a simple UNIX command line , but to be honest the easiest way is from JDeveloper itself using the HTTP analzyer by clicking on the link in the log window as shown below. At least this way the output is nicely formatted for you.


Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><depts><department><deptno>10</deptno><dname>ACCOUNTING</dname><loc>NEW YORK</loc></department><department><deptno>20</deptno><dname>RESEARCH</dname><loc>DALLAS</loc></department><department><deptno>30</deptno><dname>SALES</dname><loc>CHICAGO</loc></department><department><deptno>40</deptno><dname>OPERATIONS</dname><loc>BOSTON</loc></department></depts>

The JDeveloper project would look as follows"

Wednesday 9 March 2011

How-To: Use Oracle WebLogic Server with a JDBC GridLink Data Source

This recently created how-to I created show's how to configure and test your new Oracle WebLogic 10.3.4 JDBC GridLink Data Source. The demo here is using an 11g R2 RAC cluster with SCAN. The link is as follows which includes a web test client.

http://www.oracle.com/technetwork/middleware/weblogic/wls-jdbc-gridlink-howto-333331.html

Tuesday 8 March 2011

Accessing a JAX-RS RESTful Web Service From JRuby

In this example we access our deployed JAX-RS Web Service from Weblogic 10.3.4. For such a setup see the previous blog entry below.

Deploying a RESTful Web Service From JDeveloper 11g to Weblogic 10.3.4

1. Download the ZIP of Jersey which contains all the JARS we need here.

zip of Jersey

2. The 2 client JAR files we need are as follows. Place them into an directory where you will run the JRuby script from.

  • jersey-client-1.5.jar
  • jersey-core-1.5.jar

3. Create a JRuby script called "jax-rs-weblogic.rb" with content as follows
require 'java'

require 'jersey-client-1.5.jar'
require 'jersey-core-1.5.jar'

java_import 'com.sun.jersey.api.client.Client'
java_import 'com.sun.jersey.api.client.WebResource'

class TestJAXRSResource

  def initialize
    @client = Client.create
    @uri1 = "http://wayne-p2.au.oracle.com:7003/jaxrs-demo/jersey/helloworld/sayHello"
    @uri2 = "http://wayne-p2.au.oracle.com:7003/jaxrs-demo/jersey/helloworld/sayHelloWithName"
  end

  #add getters and setters for all attrributes  
  attr_reader :client, :uri1, :uri2
  
  def invoke_simple_method_get()
    puts "** Simple GET request .... **"
    resource = @client.resource @uri1
    response = resource.get java.lang.String.java_class
    puts response
  end

  def invoke_simple_method_get_with_param (name)
    puts "** Simple GET request with Query Param **"
    resource = @client.resource @uri2
    response = resource.queryParam("name", name).get(java.lang.String.java_class)
    puts response
  end
    
end


print "Run at #{Time.now} using JRuby #{RUBY_VERSION}\n\n"

print "** FMW Weblogic 10.3.4 JAX-RS Web Service Invoke Test **\n\n"

test = TestJAXRSResource.new
test.invoke_simple_method_get
test.invoke_simple_method_get_with_param :pas

print "\nEnded at #{Time.now} \n"

4. Edit the @uri1 and @uri2 instance variables to point to your Weblogic 10.3.4 server details and or paths to the JAX-RS Web Service.

5. Run as follows.

> jrb jax-rs-weblogic.rb

OUTPUT

Run at Tue Mar 08 07:57:54 +1100 2011 using JRuby 1.8.7


** FMW Weblogic 10.3.4 JAX-RS Web Service Invoke Test **


** Simple GET request .... **
Hello World!
** Simple GET request with Query Param **
Hello PAS


Ended at Tue Mar 08 07:57:54 +1100 2011

Wednesday 2 March 2011

Deploying a RESTful Web Service From JDeveloper 11g to Weblogic 10.3.4

I previously blogged how to create a RESTFul Web Service in JDeveloper 11g as per this entry. Here are the steps required to now deploy this to WLS 10.3.4 directly from JDeveloper itself. It's just a few basic steps.

1. Ensure you have deployed the rqeuired Jersey libraries on WLS 10.3.4 and targetted them to the managed server you are going to deploy to. Those libraries are shipped with WLS 10.3 in $WLS_HOME/common/deployable-libraries.


2. Create a weblogic.xml within your "Demo" project which includes the references to the 2 libraries above.

<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
                  xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
  <context-root>jaxrs-demo</context-root>
  <library-ref>
    <library-name>jersey-bundle</library-name>
    <specification-version>1.1.1</specification-version>
    <implementation-version>1.1.5.1</implementation-version>
  </library-ref>    
  <library-ref>
    <library-name>jsr311-api</library-name>
    <specification-version>1.1.1</specification-version>
    <implementation-version>1.1.1</implementation-version>
  </library-ref>
</weblogic-web-app>

3. Create a WAR deployment profile within your "Demo" project ensuring you don't deploy the libraries you used in JDeveloper. They are not needed as the libraries exist in WLS 10.3.4 which we are referencing. In short your WAR file would only contain 3 files here.


  1004 Wed Mar 02 13:08:34 EST 2011 WEB-INF/classes/pas/au/jdev/rs/HelloWorld.class
   635 Tue Mar 01 10:50:52 EST 2011 WEB-INF/web.xml
   780 Wed Mar 02 13:08:16 EST 2011 WEB-INF/weblogic.xml

4. Deploy the WAR file targeting it to the managed server from JDeveloper itself.

[01:10:00 PM] ----  Deployment started.  ----
[01:10:00 PM] Target platform is  (Weblogic 10.3).
[01:10:32 PM] Retrieving existing application information
[01:10:33 PM] Running dependency analysis...
[01:10:33 PM] Building...
[01:10:33 PM] Deploying profile...
[01:10:34 PM] Wrote Web Application Module to C:\jdev\jdevprod\11114\jdeveloper\jdev\mywork\JAX-RS-RESTFulWebServices\Demo\deploy\helloworld-jaxrs.war
[01:10:37 PM] Deploying Application...
[01:11:08 PM] [Deployer:149191]Operation 'deploy' on application 'helloworld-jaxrs' is initializing on 'apple'
[01:11:12 PM] [Deployer:149192]Operation 'deploy' on application 'helloworld-jaxrs' is in progress on 'apple'
[01:11:16 PM] [Deployer:149194]Operation 'deploy' on application 'helloworld-jaxrs' has succeeded on 'apple'
[01:11:24 PM] [Deployer:149191]Operation 'deploy' on application 'helloworld-jaxrs' is initializing on 'apple'
[Deployer:149192]Operation 'deploy' on application 'helloworld-jaxrs' is in progress on 'apple'
[01:11:24 PM] Application Deployed Successfully.
[01:11:28 PM] The following URL context root(s) were defined and can be used as a starting point to test your application:
[01:11:28 PM] http://10.187.81.36:7003/jaxrs-demo
[01:11:30 PM] Elapsed time for deployment:  1 minute, 30 seconds
[01:11:30 PM] ----  Deployment finished.  ----

Tuesday 1 March 2011

Developing RESTful Web Services from JDeveloper 11g (11.1.1.4)

Representational State Transfer (REST) describes any simple interface that transmits data over a standardized interface (such as HTTP) without an additional messaging layer, such as SOAP. In this example we use JDeveloper to create a basic JAX-RS Web Service from support provided within the code editor as no wizard support exists within JDeveloper 11g at this stage.

1. Download the ZIP of Jersey which contains all the JARS we need here.

zip of Jersey

2. Create a basic workspace with 2 empty projects one called "Client" and the other "Demo".

3. For the "Demo" project create a project library as shown below. Basically we want to include those JAR files we downloaded at step #1.



In short we want to include these JAR files
  • asm-3.1.jar
  • jersey-core-1.5.jar
  • jersey-server-1.5.jar

4. In the "Demo" project add a class called "HelloWorld". We just use the Java Class Wizard here as we will then use annotations to complete the class itself to make it a RESTful Web Service itself.

package pas.au.jdev.rs;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;

@Path ("/helloworld")
public class HelloWorld
{
  @Context 
  private UriInfo context;
  
  public HelloWorld()
  {
  }
  
  // Specifies that the method processes HTTP GET requests 
  @GET
  @Path("sayHello")
  @Produces("text/plain")
  public String sayHello() 
  {
     return "Hello World!";
  }
  
  // Specifies that the method processes HTTP GET requests
  @GET
  @Path("sayHelloWithName")
  @Produces("text/plain")
  public String sayHelloWithName(@QueryParam("name")String name) 
  {
     return String.format("Hello %s", name.toUpperCase());
  }  
}

5. At this point we have to create a web.xml to to expose the Jersey Servlet adapter or update an existing web.xml should one already exist in your project. JDeveloper does not automatically add the servlet class to the web.xml file. Instead, you are prompted to confirm whether you want to add it when you call a JAX-RS method from your code. For example:

@Path ("/helloworld")

When you place the cursor on this line of code above you will see the option to configure web.xml in the left hand gutter of the code editor.

Note: Why is the web.xml file not updated automatically? In the future, when you deploy to a Java EE 6.0 container, an update to the web.xml will not be required. Therefore, this is set up as an optional activity.

The web.xml would then look as follows.
<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app 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"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>jersey</servlet-name>
    <url-pattern>/jersey/*</url-pattern>
  </servlet-mapping>
</web-app>

6. In the application navigator you will notice that your class now is known as a Web Service using the Web Service icon which JDeveloper has used for JAX-WS and JAX-RPC 1.4 Web Services. At this point we can run it to deploy it to the Integrated Server from JDeveloper by selecting the "Run" context menu of your RESTful Web Service.

7. If all goes well you should see at the bottom of the log window something as follows.

[09:32:34 PM] ----  Deployment finished.  ----
Run startup time: 5585 ms.
[Application JAX-RS-RESTFulWebServices deployed to Server Instance IntegratedWebLogicServer]


Target Application WADL -- http://localhost:7101/jaxrs-demo/jersey/application.wadl


Target URL -- http://localhost:7101/jaxrs-demo/jersey/helloworld/sayHello

8. At this point we can test the JAX-RS resource using a web browser, for example. Yes even though we are using plain text response that would still work. Enter the URL below into a browser and verify output as shown below.



Note: You could even click on the "target URL" from the log window if you want to use the "HTTP Analyzer" itself which would be another quick way to do this as shown below


9. Now we know it works we simply will invoke it from a client. To do this we edit the "Client" project properties and ensure we have added the 3 JAR files we obtained from step #1 above.


In short we want to include these JAR files
  • jersey-client-1.5.jar
  • jersey-core-1.5.jar
10. In the "Client" project add a test class as follows.
package pas.au.jdev.rs.client;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;

public class HelloWorldClient
{
  public HelloWorldClient()
  {
  }

  public static void main(String[] args)
  {
    Client c = Client.create();
    System.out.println("** Simple GET request .... **");
    WebResource resource = 
      c.resource("http://localhost:7101/jaxrs-demo/jersey/helloworld/sayHello");
    String response = resource.get(String.class);
    
    System.out.println(response);
    
    System.out.println("** Simple GET request with Query Param **");
    WebResource resource2 = 
      c.resource("http://localhost:7101/jaxrs-demo/jersey/helloworld/sayHelloWithName");
    String response2 = resource2.queryParam("name", "pas").get(String.class);
    
    System.out.println(response2);
    
  }
}

11. Run the class and verify it shows output as follows.


** Simple GET request .... **
Hello World!
** Simple GET request with Query Param **
Hello PAS


The JDeveloper workspace would look as follows