Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAX-WS Web Service without Java EE Containers

Tags:

jax-ws

I want to build a JAX-WS Web Service that will run in Java SE 6.0 (no container, just Standard Edition java).

I started with an old Tutorial described here http://today.java.net/pub/a/today/2007/07/03/jax-ws-web-services-without-ee-containers.html

However I am running into some problems.

When I run wsgen against my WebService class (acximImpl) it will generate the class files for operation methods and the class that gets returned from the operation but it will not generate the code for the classes that are passed as parameters to the operation method.

So when I use a client to call the queryParts1() method I get back a soap fault saying "Cannot find dispatch method for {http://com/activant/web/services/partorder}queryParts1Request"

I am using NetBeans IDE 7.0.1

My build.xml that gets run by NetBeans looks like this: (it gets run after netbeans compiles my class files)

<project name="acximserver" default="default" basedir=".">
<description>Builds, tests, and runs the project acximserver.</description>
<import file="nbproject/build-impl.xml"/>
<target name="-post-compile" >
  <echo message="Generating artifacts..."/>
  <exec executable="C:/acxim/BuildTools/JAX-WS/2.2.3/bin/wsgen.bat">
      <env key="JAVA_HOME" value="C:\BuildTools\jdk\1.6.0.24"/>
      <arg value="-verbose"/>
      <arg value="-keep"/>
      <arg value="-cp"/>
      <arg value="C:/Connectivity/APFCLSDK/Components/acximserver/build/classes"/>
      <arg value="-d"/>
      <arg value="${annotation.processing.source.output}"/>
      <arg value="com.epicor.acximsdk.acximserver.acximImpl"/>
  </exec>
  <javac debug="true"
         srcdir="${annotation.processing.source.output}"
         destdir="C:/Connectivity/APFCLSDK/Components/acximserver/build/classes"
         classpath="${acxclasspath}"/>

</target>

My Main Class file look like this:

package com.epicor.acximsdk.acximserver;

import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.bind.annotation.XmlElement;
import org.apache.log4j.Logger;

public class Acximserver {
private Endpoint endpoint = null;
private static final Logger logger = Logger.getLogger("com.epicor.acximsdk.acximserver");

public Acximserver() {
    System.out.println("Acximserver constructor called.");
    endpoint = Endpoint.create(new acximImpl());
    logger.info("Inside Acximserver constructor");
}
private void publish() {
    endpoint.publish("http://localhost:1970/acximservice/PartOrderMgr");
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    // TODO code application logic here
    System.out.println("Acximserver main() function called");
    Acximserver acxim = new Acximserver();
    acxim.publish();
    System.out.println("Acximserver Open for business at:");
    System.out.println("  http://localhost:1970/acximservice/PartOrderMgr");
}

}

My WebService class looks like this:

package com.epicor.acximsdk.acximserver;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import javax.xml.bind.annotation.XmlElement;
import javax.jws.HandlerChain;

@WebService(
    name = "acximservice",
    serviceName = "PartOrderMgr",
    targetNamespace = "http://com/activant/web/services/partorder"
    )
@HandlerChain(file="soaphandler.xml")      // Setup some custom classes to intercept messages for logging.
public class acximImpl {
public acximImpl() {
    System.out.println("acximImpl constructor called.");
}

@WebMethod(operationName = "queryParts1")
@WebResult(name = "queryParts1Response")
public QueryParts1Response queryParts1(
       @WebParam(name = "Credentials", header = true)                      Credentials credentials,
       @WebParam(name = "queryParts1Request") @XmlElement(required = true) QueryParts1Request request
       //Credentials credentials,
       //QueryParts1Request request
       )
{
    String tracknum = "";
    QueryParts1Response response = new QueryParts1Response();

    if(credentials != null) {
        System.out.println("Token = " + (credentials.getToken()==null ? "null" : credentials.getToken()));
        System.out.println("TokenSignature = " + (credentials.getTokenSignature()==null ? "null" : credentials.getTokenSignature()));
    } else
        System.out.println("credentials is null");

    if(request != null) {
        if(request.metadata != null) {
            System.out.println("timeout = " + request.metadata.gettimeout());
            System.out.println("ACXTrackNum = " + (request.metadata.getACXTrackNum()==null ? "null" : request.metadata.getACXTrackNum()));
            if(request.metadata.getACXTrackNum() != null)
                tracknum = request.metadata.getACXTrackNum();
        }
        else {
            System.out.println("metadata is null");
        }

        if(request.requestString != null)
            System.out.println("reqeust = " + request);
        else
            System.out.println("requestString is null");
    }
    else
        System.out.println("request is null");

    response._return = createACXNotification("buyid", "sellid", tracknum, "INFO", "0", "Service is working");
    return response;
}

public String makeRequestHeader(String acxRequestName) {
    return "<?xml version=\"1.0\" ?>" +
           "<!DOCTYPE " + acxRequestName + " SYSTEM '" +
           "http://www.aconnex.com/DTD" + "/" + acxRequestName +
           "_v1_0" + ".dtd'>";
}
protected String  createACXNotification(String Buy, String Sell, String Track, String Sev, String Code, String Msg) {
    String       version = "1.0"; // somehow make this configurable.
    StringBuffer buf     = new StringBuffer();
    buf.append(makeRequestHeader("ACXNotificationResponse"));
    buf.append("<ACXNotificationResponse><Envelope><BuyPartnerID>");
    buf.append(Buy);
    buf.append("</BuyPartnerID><DocVersNum>");
    buf.append(version);
    buf.append("</DocVersNum><DocGenBy>Epicor javaSDK</DocGenBy></Envelope>");
    buf.append("<NotificationResponse><ACXTrackNum>");
    buf.append(Track);
    buf.append("</ACXTrackNum><SellPartnerID>");
    buf.append(Sell);
    buf.append("</SellPartnerID><Severity>");
    buf.append(Sev);
    buf.append("</Severity><Code>");
    buf.append(Code);
    buf.append("</Code><Msg>");
    buf.append(Msg);
    buf.append("</Msg></NotificationResponse></ACXNotificationResponse>");
    return buf.toString();
}

}

The class QueryParts1Response returned by the queryParts1() method that does get generated looks like this:

package com.epicor.acximsdk.acximserver;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


//@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "queryParts1Response", propOrder = {
"_return"
})
@XmlRootElement(name = "queryParts1Response")
public class QueryParts1Response {

@XmlElement(name = "return", required = true)
protected String _return;

/**
 * Gets the value of the return property.
 * 
 * @return
 *     possible object is
 *     {@link String }
 *     
 */
public String getReturn() {
    return _return;
}

/**
 * Sets the value of the return property.
 * 
 * @param value
 *     allowed object is
 *     {@link String }
 *     
 */
public void setReturn(String value) {
    this._return = value;
}

}

The QueryParts1Request class that is a parameter to the queryParts1() method and does not get generated looks like this:

package com.epicor.acximsdk.acximserver;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


//@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://com/activant/web/services/partorder", propOrder = {
"requestString",
"metadata"
})
@XmlRootElement(name = "queryParts1Request")
public class QueryParts1Request {

@XmlElement(name = "requestString", required = true)
protected String requestString;
@XmlElement(name = "metadata", required = true)
protected Metadata1TYPE metadata;

/**
 * Gets the value of the requestString property.
 * 
 * @return
 *     possible object is
 *     {@link String }
 *     
 */
public String getRequestString() {
    return requestString;
}

/**
 * Sets the value of the requestString property.
 * 
 * @param value
 *     allowed object is
 *     {@link String }
 *     
 */
public void setRequestString(String value) {
    this.requestString = value;
}

/**
 * Gets the value of the metadata property.
 * 
 * @return
 *     possible object is
 *     {@link Metadata1TYPE }
 *     
 */
public Metadata1TYPE getMetadata() {
    return metadata;
}

/**
 * Sets the value of the metadata property.
 * 
 * @param value
 *     allowed object is
 *     {@link Metadata1TYPE }
 *     
 */
public void setMetadata(Metadata1TYPE value) {
    this.metadata = value;
}

}

How do I get wsgen to generate the class files for the objects in the method parameters lists? Note that the main class is using the EndPoint class to publish the url that the web services is listening on.

Any help would be greatly appreciated. Thanks.

like image 345
Richard Avatar asked Jul 14 '26 19:07

Richard


1 Answers

I was trying to do this too (build a JAX-WS Web Service that will run in Java SE 6.0 (no container, just Standard Edition java)) and I found an easiest way. Please check this two tutorials http://www.ibm.com/developerworks/webservices/tutorials/ws-eclipse-javase1/index.html and http://technology.amis.nl/2009/06/05/publish-a-webservice-from-a-poja-plain-old-java-application-that-is-out-of-the-container-using-endpoint-class/

like image 112
arojasp Avatar answered Jul 25 '26 10:07

arojasp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!