Month: March 2012

JEE Web Service with Annotations: SOAP Based

The evolution of WebServices technology, specially JAX-WS, has eased the implementation of JEE components as Services. The focus of the blog is to show how you can implement EJB’s as services. Many would argue about leaving services as POJO’s, but there are drawbacks to exposing your services as POJO’s. If you are running in a JEE Application Server, it’s to your benefit to leverage the container as much as possible, especially for transaction handling and security.

For those of you who have stayed away from EJB, don’t worry. Developing a EJB 3.0 service is the same as you would develop a POJO based service; except for the following Annotations (JSR-181):

  1. @Stateless – tells the container that the class is a Stateless Session Bean
  2. @WebService – tells the container that the class is also a WebService.

Let’s look at a simple “Greet Me Service” in order to illustrate. The GreetMeService implements a Service Endpoint Interface.  In order to create the service, first define the Interface.

The interface defines the methods that must be implemented by the class. From a Web Service perspective, it defines the web service operations. Let’s look at the Service Endpoint Interface.

import java.rmi.Remote;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import java.rmi.RemoteException;

@WebService(name = “GreetMeEJBBeanService”)
@SOAPBinding(style = Style.DOCUMENT)
public interface GreetMeEJBBeanService extends Remote {
@WebMethod(operationName = “greetMe”)
@WebResult(targetNamespace=”http://com.santisij.greetme/types”,
name=”greeting”)
public String greetMe(@WebParam(targetNamespace = “http://com.santisij.greetme/input”,name = “name”,mode = Mode.IN)String name) throws RemoteException;

//The RemoteException must be thrown by the EJB
}

I am assuming that you are familiar with the different types of WebService Bindings- Document or RPC and whether it’s Literal or Encoded. The JAX-WS specification defines the web service binding style as Document by default.   It does not hurt to define the Binding as DOCUMENT, but you can easily leave out the @SOAPBinding annotation.

The key difference between Document and RPC is that the Document style has full XML documents, while RPC indicates that the underlying SOAP message contains parameters in the request and response values in the response message.

Now that we defined our Interface let’s implement the method/operations:

import javax.ejb.Remote;
import javax.ejb.Stateless;

import javax.jws.WebService;

@Stateless(name = “GreetMeEJB”, mappedName = “GreetMe-GreetMeEJB”)
@Remote(GreetMeEJBBeanService.class)
@WebService(portName = “GreetMeEJBBeanServicePort”, endpointInterface = “com.santisij.greetme.GreetMeEJBBeanService”)
public class GreetMeEJBBean{

public String greetMe(String name){
StringBuilder sb = new StringBuilder();
sb.append(“This is the Greeting Service….”);
sb.append(“Hello “);
sb.append(name);

return sb.toString();
}
}

The advantage of using the JEE spec is that this EJB is both a web service and an EJB.  If you need to invoke this service from the same JVM, you don’t have to go through the SOAP stack in order to get your response.
Here’s a simple client that looks up the EJB from the JNDI tree and invokes the GreetMeService.
public class GreetMeEJBClient {

public static void main(String [] args) {
String name = “Juan”;
String result = null;
try {
final Context context = getInitialContext();
GreetMeEJBBeanService greetMeEJB = (GreetMeEJBBeanService)context.lookup(“GreetMe-GreetMeEJB#com.santisij.greetme.GreetMeEJBBeanService”);
System.out.println(“I got the Context: executing method”);
result = greetMeEJB.greetMe(name);
System.out.println(“result from RMI: “+result);
} catch (Exception ex) {
ex.printStackTrace();
}
}

private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put(Context.INITIAL_CONTEXT_FACTORY, “weblogic.jndi.WLInitialContextFactory” );
env.put(Context.PROVIDER_URL, “t3://localhost:7001″);
return new InitialContext( env );
}
}

I used JDeveloper to build and deploy the service to WebLogic, but you could easily build and deploy the service to Glassfish Server with Eclipse.  In addition, make sure that you generate/view the WSDL file. If your service location has a the value ” REPLACE …”, you will have to replace the service location with the URL of your service.

WebLogic – http://myhost:7001/GreetMeEJBBean/GreetMeEJBBeanService
Take a look at the WSDL: http://localhost:7001/GreetMeEJBBean/GreetMeEJBBeanService?wsdl

I  use soapUI – a great tool to test your services – this is the URL that you want to point to.  The following links provide great reference material …

http://java.sun.com/webservices/docs/1.6/tutorial/doc/

There are several books that dive into the JAX-WS and EJB 3.x specifications (Just search for your favorite publisher)

RUL-00026

The following description is from the oracle online documentation:

RUL-00026: exception in invoked Java method {0} {1,choice,0#|0<at line {1,number,integer}} {2,choice,0#|0< column {2,number,integer}} {1,choice,0#|0< } {3,choice,0#|0<in {4}}Cause: A Java method invoked from RL threw an exception.

Action: Investigate the root cause of the exception thrown by the Java method. It is available as the cause of the exception thrown with this message.Level: 1

Type: ERROR

Impact: Programmatic

This error is caused by the Oracle RL executed in the business engine. If you have not had the chance, create a debug function for your custom function. (I will create a short tutorial shortly) Then, test the function.

Also, validate the XML input in order to make sure that all required elements are being submitted.

WebLogic 10.3.5 Linux Install

I finally had the chance to capture the wizard as I configured a WebLogic server for development. The target OS is CentOS 32-bit, long story, but the wizard will work the same for other OS flavors.

The software, jdeveloper version 11.1.1.5.0, which includes WebLogic Server 10.3.5. I am glad that Oracle started to package WebLogic Server with jdeveloper. Since we are using the jdeveloper installer, the ADF libraries need to be selected during the install process.

This blog assumes that you successfully installed jdeveloper. Once the installer has completed the install, select the run quickstart checkbox.

Once QuickStart starts, click on the “Getting Started with WebLogic 10.3.5”. Next, on the Welcome screen select the “Create a WebLogic Domain”.

On the next screen, “Select Domain Source”, you must specify the components that the domain will support. In our case, it’s extremely important that our domain support ADF. The ADF libraries are defined as “Oracle – JRF -11.1.1.0 – oracle common”. Also, I selected the JAX-RPC and JAX-WS support. I choose not to install the Oracle WSM Policy Manager and SIP Server. And click next.

On the next screen, you must specify the “Domain Name and Location”. You can place the domain anywhere you would like. Since this is a development environment, I chose to install it at the Middleware Home directory, under “user_projects”. And click next.


On the screen, “Configure Administrator username and password”, make the necessary changes to suit your needs and preferences. And click next.

On the screen, “Configure Server Start Node and JDK”, select the server mode and the jdk. In this scenario, I chose for the server to be in development mode and for the jdk to be JRockit. Once your selections are made, click next.


The “Select Optional Configuration” screen will appear. On this screen we chose to set up an Administration server and a Managed Server. Depending on your configuration, the Administrator server will be sufficient for you to deploy and test your application. Since this is a Development environment configuration, I am not going to into detail about clusters and HA. Make your selection and click next.

Note: Depending on your selection you will have additional screens to covered on this blog.

On the next screen, “Configure the Admin Server”, Modify or accept the default user and provide a password. If you need SSL you can enable it here or after the install on the console. Define the port that the Admin server will listen. In our case, the default port of 7003 was selected. Click next when you are done.

If you chose to add Managed Servers, the next screen will look familiar. Otherwise ignore. In order to configure a managed server, perform the following 3 steps.

1. Click the Add button

2. Provide a name for the server: wls_ms_1

3. Define the Listen address and SSL for each Managed Server: 7003

Repeat Steps 1-3 for each server that you want to add as a managed server. Click next when you are done. The next screen is used to configure clusters, ignore at this time.

On the next screen we will define a Machine. For a development environment you don’t need this, but it’s good practice to define. The machine is the logical representation of the physical machine that hosts one or more WebLogic server instances. In a cluster, WebLogic Server uses machines to ensure that the server session data is replicated to other physical servers. Click the Add button and define at least one machine. Place close attention to the Node Listen Port, the node is used to communicate between the Admin server and the managed servers. Click next when done.

Name:<dev_machine_1>

Node Manager Listen Address:<localhost>

Node Manager Listen Port:<5556>

On the “Assign Servers to Machines” screen, add the Admin and Managed Server. Click next.

On the next screen, we will get a summary of all the components selected. Click next.


Assuming that everything went well, your domain will be created satisfactory.

You now have a WebLogic Domain with an Admin and Managed Server configuration. I will add additional WebLogic posts as time permits.

BEA-141281

Recently, I encountered the following error while starting up my Admin Server on my WebLogic Domain. BEA-141281 This error is caused when the AdminServer.lok file already exists on your Admin’s server directory. In order to get rid of the error, navigate to your server directory:

### MW_HOME=/opt/oracle/middleware

### i.e. – $MW_HOME/user_projects/domains/servers/AdminServer/tmp