Tuesday, 27 March 2012

Converting JAX-WS examples from NB-GlassFish to Eclipse-Tomcat



This is a demo of converting JavaEE5-6 jaxws examples from NetBeans-GlassFish to Eclipse-Tomcat and Eclipse-GlassFish.
You can find JAVAEE6 examples at
http://docs.oracle.com/javaee/6/tutorial/doc/ (page 366).

The service part remains the same in Eclipse.


package helloservice.endpoint;
import javax.jws.WebService;
import javax.jws.webMethod;

@WebService
public class Hello {
private String message = new String("Hello, ");
public void Hello() {
}
@WebMethod
public String sayHello(String name) {
return message + name + ".";
}
}

But the client side causes problems when/if implemented as below(page 368).:

package appclient;
import helloservice.endpoint.HelloService;
import javax.xml.ws.WebServiceRef;

public class HelloAppClient {
@WebServiceRef(wsdlLocation =
"META-INF/wsdl/localhost_8080/helloservice/HelloService.wsdl")

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
System.out.println(sayHello("world"));
}
private static String sayHello(java.lang.String arg0) {
helloservice.endpoint.Hello port = service.getHelloPort();
return port.sayHello(arg0);
}
}

My Eclipse-TOMCAT version follows:
/*
* Copyright 2011 Oracle and/or its affiliates.
* All rights reserved. You may not modify, use,
* reproduce, or distribute this software except in
* compliance with the terms of the License at:
* http://developers.sun.com/license/berkeley_license.html
*/

package webclient;

import helloservice.endpoint.HelloService;
import java.io.IOException;
import java.io.PrintWriter;
import java.rmi.RemoteException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.rpc.ServiceException;
import javax.xml.ws.WebServiceRef;


@WebServlet(name = "HelloServlet", urlPatterns = {"/HelloServlet"})
public class HelloServlet extends HttpServlet {
//@WebServiceRef(wsdlLocation = "WEB-INF/wsdl/ars-PC_8080/helloservice/HelloService.wsdl")
@WebServiceRef(wsdlLocation = "http:///ars-PC:8080/helloservice/HelloService?wsdl")
public HelloService service;

/**
* Processes requests for both HTTP <code>GET</code>
* and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(
HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();

try {
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Servlet HelloServlet</title>");
out.println("</head>");
out.println("<body>");
out.println(
"<h1>Servlet HelloServlet at " + request.getContextPath()
+ "</h1>");
out.println("<p>" + sayHello("world") + "</p>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}

// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}

/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(
HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}

/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
} // </editor-fold>

private String sayHello(java.lang.String arg0) {
try {
helloservice.endpoint.Hello port = service.getHello();
// port = service.getHelloPort();
return port.sayHello(arg0);
} catch(ServiceException e){}
catch(RemoteException re){};
return "error";
}
}

The problems I met during this effort:

javax.servlet.ServletException: Error instantiating servlet class webclient.HelloServlet
...
root cause

javax.naming.NameNotFoundException: Name webclient.HelloServlet is not bound in this Context
org.apache.naming.NamingContext.lookup(NamingContext.java:803)
org.apache.naming.NamingContext.lookup(NamingContext.java:159)

This error stops when I comment the @WebServiceRef line. But then the service.getHello() does not work due to the null service from the lack of injection.

Some other problems I met while dealing with this problem:
After
wsdlDocumentLocation = new URL(
// "http://localhost:8080/helloservice/HelloService?wsdl");
"http://localhost:8080/helloservice/services/Hello");

Mar 19, 2012 7:57:32 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Hello] in context with path [/webclient] threw exception
javax.xml.ws.WebServiceException: {http://endpoint.helloservice/}HelloService is not a valid service. Valid services are: {http://endpoint.helloservice}HelloService
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:272)
at ...

I also got this at one point:

type Exception report
descriptionThe server encountered an internal error () that prevented it from fulfilling this request.
exception
com.sun.xml.ws.util.ServiceConfigurationError: com.sun.xml.ws.api.pipe.TransportPipeFactory: Provider com.sun.enterprise.jbi.serviceengine.bridge.transport.JBITransportPipeFactory is specified in bundle://293.0:0/META-INF/services/com.sun.xml.ws.api.pipe.TransportPipeFactory but not found
note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.1 logs.

The solution of the problem is:


nlibraies.properties
libs.CopyLibs.classpath=\
${base}/CopyLibs/org-netbeans-modules-java-j2seproject-copylibstask.jar
libs.javaee-endorsed-api-6.0.classpath=\
${base}/javaee-endorsed-api-6.0/javax.annotation.jar;\
${base}/javaee-endorsed-api-6.0/jaxb-api-osgi.jar;\
${base}/javaee-endorsed-api-6.0/webservices-api-osgi.jar
libs.javaee-endorsed-api-6.0.javadoc=\
${base}/javaee-endorsed-api-6.0/javaee6-doc-api.zip

--------------------------------
C:\Users\ars\Desktop\ARSnbWebService\jaxws\helloservice\lib\javaee-endorsed-api-6.0
webservices-api-osgi.jar
jaxb-api-osgi.jar
javax.annotation
jaxrpc
saaj
wsdl4j



The NetBeans-GlassFish uses Metro Services or JAX-WS Reference Implementation which utilizes the above jars at the top. The Eclipse-Tomcat uses the above jar files and the AXIS implementation. So, there are structural differences in the implementation of JAX-WS.

My solution for Eclipse-Tomcat conversion of the above Javaee5-6 example is:

/*
* Copyright 2011 Oracle and/or its affiliates.
* All rights reserved. You may not modify, use,
* reproduce, or distribute this software except in
* compliance with the terms of the License at:
* http://developers.sun.com/license/berkeley_license.html
*/

package webclient;

import helloservice.endpoint.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.rmi.RemoteException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import javax.xml.ws.Service;

import org.apache.axis.AxisFault;

import java.net.MalformedURLException;
import java.net.URL;

@WebServlet(name = "HelloServlet", urlPatterns = { "/HelloServlet" })
public class HelloServlet extends HttpServlet {

/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code>
* methods.
*
* @param request
* servlet request
* @param response
* servlet response
* @throws ServletException
* if a servlet-specific error occurs
* @throws IOException
* if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException, AxisFault ,Exception {
response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();

try {
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>Servlet HelloServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet HelloServlet at "
+ request.getContextPath() + "</h1>");
out.println("<p>" + sayHello("world") + "</p>");
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}

// <editor-fold defaultstate="collapsed"
// desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request
* servlet request
* @param response
* servlet response
* @throws ServletException
* if a servlet-specific error occurs
* @throws IOException
* if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try{
processRequest(request, response);
} catch(AxisFault af){}
catch(Exception e){}
}

/**
* Handles the HTTP <code>POST</code> method.
*
* @param request
* servlet request
* @param response
* servlet response
* @throws ServletException
* if a servlet-specific error occurs
* @throws IOException
* if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try{
processRequest(request, response);
} catch(AxisFault af){}
catch(Exception e){}
}

/**
* Returns a short description of the servlet.
*
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
} // </editor-fold>

private String sayHello(java.lang.String arg0) throws AxisFault ,Exception {

try {
// URL wsdlDocumentLocation = null;
// try {
// wsdlDocumentLocation = new URL(
// "http://localhost:8080/helloservice/HelloService?wsdl");
// //"http://localhost:8080/helloservice/services/Hello");
// } catch (MalformedURLException e) {
// e.printStackTrace();
// }
// QName qname = new QName("http://endpoint.helloservice/", "HelloService");
//
// Service service = Service.create(wsdlDocumentLocation, qname);
// System.out.println("aaaaaaaaaaaaa3");
// Hello hello = service.getPort(Hello.class);
// System.out.println("aaaaaaaaaaaaa4");
// return hello.sayHello(arg0);
// } catch (RemoteException re) {
// }
// return ("error");
//
// }
HelloSoapBindingStub srv = new HelloSoapBindingStub(
new URL("http://localhost:8080/helloservice/services/Hello"),
new HelloServiceLocator());
return srv.sayHello(arg0);
} catch(AxisFault af){}
return "error";

}
}

Please notice the changes that replace the commented code. I used a stub and its binding to the web service address and a locator to call the sayHello. The rest of the staff is pretty straight forward but if any problems do not hesitate to contact me at arsaral(at)yahoo.com .

An example of Eclipse-GlassFish conversion of the NetBeans-GlassFish version will follow.