Web-Service mittels dynamische Proxies nutzen


#1

Hallo,

ich habe einen Web-Service und einen dazugehörigen Clienten geschrieben. Nutze ich Glassfish , so funktioniert die Anbindung reibungslos. Wenn ich den Web-Service aber in axis( auf dem tomcat laufend) deploye, dann kann ich mich zwar verbinden, aber bekomme die Meldung : undefined port type , sobald ich auf die Methode(Operation) des Web-Services zugreife. Mit ist weiter hin ausgefallen, das die beiden generierten wsdl-Files (von Glassfish und axis auf tomcat) sich unterschieden.

wsdl unter tomcat :

[XML]
<wsdl:definitions targetNamespace=“http://webTest”>
wsdl:documentationTest von Web-Services.</wsdl:documentation>
wsdl:types
<xs:schema attributeFormDefault=“qualified” elementFormDefault=“qualified” targetNamespace=“http://webTest”>
<xs:element name=“check”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” name=“args0” nillable=“true” type=“xs:string”/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=“checkResponse”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” name=“return” nillable=“true” type=“xs:string”/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name=“checkRequest”>
<wsdl:part name=“parameters” element=“ns:check”/>
</wsdl:message>
<wsdl:message name=“checkResponse”>
<wsdl:part name=“parameters” element=“ns:checkResponse”/>
</wsdl:message>
<wsdl:portType name=“WebTestServicePortType”>
<wsdl:operation name=“check”>
<wsdl:input message=“ns:checkRequest” wsaw:Action=“urn:check”/>
<wsdl:output message=“ns:checkResponse” wsaw:Action=“urn:checkResponse”/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name=“WebTestServiceSoap11Binding” type=“ns:WebTestServicePortType”>
<soap:binding transport=“http://schemas.xmlsoap.org/soap/http” style=“document”/>
<wsdl:operation name=“check”>
<soap:operation soapAction=“urn:check” style=“document”/>
wsdl:input
<soap:body use=“literal”/>
</wsdl:input>
wsdl:output
<soap:body use=“literal”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name=“WebTestServiceSoap12Binding” type=“ns:WebTestServicePortType”>
<soap12:binding transport=“http://schemas.xmlsoap.org/soap/http” style=“document”/>
<wsdl:operation name=“check”><soap12:operation soapAction=“urn:check” style=“document”/>
wsdl:input
<soap12:body use=“literal”/>
</wsdl:input>
wsdl:output
<soap12:body use=“literal”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name=“WebTestServiceHttpBinding” type=“ns:WebTestServicePortType”>
<http:binding verb=“POST”/>
<wsdl:operation name=“check”>
<http:operation location=“check”/>
wsdl:input
<mime:content type=“application/xml” part=“parameters”/>
</wsdl:input>
wsdl:output
<mime:content type=“application/xml” part=“parameters”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name=“WebTestService”>
<wsdl:port name=“WebTestServiceHttpSoap11Endpoint” binding=“ns:WebTestServiceSoap11Binding”>
<soap:address location=“http://localhost:8035/axis2/services/WebTestService.WebTestServiceHttpSoap11Endpoint/”/>
</wsdl:port>
<wsdl:port name=“WebTestServiceHttpSoap12Endpoint” binding=“ns:WebTestServiceSoap12Binding”>
<soap12:address location=“http://localhost:8035/axis2/services/WebTestService.WebTestServiceHttpSoap12Endpoint/”/>
</wsdl:port>
<wsdl:port name=“WebTestServiceHttpEndpoint” binding=“ns:WebTestServiceHttpBinding”>
<http:address location=“http://localhost:8035/axis2/services/WebTestService.WebTestServiceHttpEndpoint/”/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
[/XML]

wsdl vom Glassfish generiert, wo auch alles auf anhieb lief:

[XML]

[/XML]

Web-Service Interface:

package webTest;

import javax.jws.*;
@WebService

public interface WebTest 
{
    @WebMethod(operationName="check", action="check")
    public String check(String name);
}

Web-Service Klasse

package webTest;

import javax.jws.*;
import javax.ejb.*;

@WebService(endpointInterface="webTest.WebTest", serviceName="WebTest", portName="WebTestPort")
@Stateless
public class DefaultWebTest 
implements WebTest
{    
    
    public String check(String name) 
    {
        return "test check : " + name;
    }
}

services.xml

[XML]

Test von Web-Services.

webTest.WebTest


   <!--actionMapping>urn:getLogger</actionMapping-->
</operation>
[/XML]

Client-Application:


import javax.xml.ws.*;
import java.net.*;
import javax.xml.namespace.*;
import webTest.*;
import base.*;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author seann
 */
public class WebTestClient 
{
    public WebTestClient() 
    {
        
    }
    
    public static void main(String[] args) 
    {
        WebTestClient webTestClient = new WebTestClient();
        webTestClient.test();
    }
    
    
    public void test() 
    {
        try {
            //URL url = new URL("http://localhost:8035/axis2/services/WebTestService?wsdl");  //tomcat
            URL url = new URL(" http://localhost:8080/WebTest/DefaultWebTest?wsdl");  //glassfish
            //String nameSpace = "http://webTest"; //Namespace tomcat
            String nameSpace = "http://webTest/"; //Namespace glassfish
            String port = "WebTestPort"; //glassfish
            //String port = "WebTestServiceHttpEndpoint"; //tomcat
            Service service = Service.create(url, new QName(nameSpace, "WebTest"));
            //WebTest webTest = service.getPort(webTest.WebTest.class);
            WebTest webTest = service.getPort(new QName( nameSpace
                                                       , port)
                                             ,WebTest.class
                                             );
            System.out.println("" + webTest.getClass().getCanonicalName() );
            
            //ObjectSerializerToXML s = new ObjectSerializerToXML();
            System.out.println(webTest.check("main"));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

Bei der Verbindung zum Web-Service auf dem Tomcat kommt es zur einer Exception “undefined port type” in Zeile 47 des Clienten.

Die Angabe portName=“WebTestPort” beim Service wird vom Glassfish umgesetzt, der Tomcat scheint dessen keine Bedeutung zu schenken.

Wie kann ich richtig Taggen, sodass ich eine konsistente Anbindung bekomme, egal auf welchem Server mein Web-Service läuft?

Vielen Dank schon im voraus.

lg JSeann


#2

Ich habe folgendes bei dem Versuch mein Web-Service unter axis2 auf dem tomcat zu nutzen herausgefunden.

Wie oben ersichtlich, generiert mir axis 3 ServicePorts:
**
UpdateFAOtoFSWServiceHttpEndpoint
UpdateFAOtoFSWServiceHttpSoap11Endpoint
UpdateFAOtoFSWServiceHttpSoap12Endpoint
**

Ich bekomme für die folgenden 3 Implementierungen unterschiedliche Exceptions.

Die Exceptions werden durch folgende Zeile ausgelöst:

((fao.UpdateFAOtoFSW)proxy).getTables("blupp");

Vorweg, die Methode getTables ist in dem Proxy-Objekt vorhanden.

if(proxy.getClass().getMethods() != null && proxy.getClass().getMethods().length > 0) 
            {
                for(int index = 0; index < proxy.getClass().getMethods().length; index++)
                {
                    System.out.println(proxy.getClass().getMethods()[index].toString());
                    System.out.println(proxy.getClass().getDeclaredMethods()[index].toString());
                }
            }

Ausgabe:

public final boolean com.sun.proxy.$Proxy22.equals(java.lang.Object)
public final java.lang.String com.sun.proxy.$Proxy22.toString()
public final int com.sun.proxy.$Proxy22.hashCode()
public final void com.sun.proxy.$Proxy22.close()
public final java.util.Map com.sun.proxy.$Proxy22.getRequestContext()
public final java.lang.String com.sun.proxy.$Proxy22.getTables(java.lang.String)
public final javax.xml.ws.Binding com.sun.proxy.$Proxy22.getBinding()
public final void com.sun.proxy.$Proxy22.setAddress(java.lang.String)
public final void com.sun.proxy.$Proxy22.setOutboundHeaders(com.sun.xml.internal.ws.api.message.Header[])
public final void com.sun.proxy.$Proxy22.setOutboundHeaders(java.util.List)
public final void com.sun.proxy.$Proxy22.setOutboundHeaders(java.lang.Object[])
public final com.sun.xml.internal.ws.api.client.WSPortInfo com.sun.proxy.$Proxy22.getPortInfo()
public final java.util.Map com.sun.proxy.$Proxy22.getResponseContext()
public final com.sun.xml.internal.ws.api.addressing.WSEndpointReference com.sun.proxy.$Proxy22.getWSEndpointReference()
public final javax.xml.ws.EndpointReference com.sun.proxy.$Proxy22.getEndpointReference(java.lang.Class)
public final javax.xml.ws.EndpointReference com.sun.proxy.$Proxy22.getEndpointReference()
public final com.sun.org.glassfish.gmbal.ManagedObjectManager com.sun.proxy.$Proxy22.getManagedObjectManager()
public final java.util.List com.sun.proxy.$Proxy22.getInboundHeaders()
public static boolean java.lang.reflect.Proxy.isProxyClass(java.lang.Class)
public static java.lang.Class java.lang.reflect.Proxy.getProxyClass(java.lang.ClassLoader,java.lang.Class[]) throws java.lang.IllegalArgumentException
public static java.lang.Object java.lang.reflect.Proxy.newProxyInstance(java.lang.ClassLoader,java.lang.Class[],java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException
public static java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

Methode 1

public void test1() 
    {
        try 
        {
            String serviceName = "UpdateFAOtoFSWService";            
            String servicePort = "UpdateFAOtoFSWServiceHttpEndpoint";            
            String url = "http://localhost:8041/axis2/services/UpdateFAOtoFSWService";            
            String namespace = "http://fao";
            Service service = Service.create(new URL(url + "?wsdl") 
                                            ,new QName(namespace , serviceName));
            
            Object proxy = service.getPort(new QName(namespace, servicePort)
                                          ,fao.UpdateFAOtoFSW.class);
            
            ((fao.UpdateFAOtoFSW)proxy).getTables("blupp");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        } 
    }

Ergebnis:

**javax.xml.ws.WebServiceException: Unsupported endpoint address: **
at com.sun.xml.internal.ws.api.pipe.TransportTubeFactory.create(TransportTubeFactory.java:133)
at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:119)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:626)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:585)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:570)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:467)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:308)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:146)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:129)
at com.sun.proxy.$Proxy22.getTables(Unknown Source)
at fao.UpdateFAOtoFSWClient.test1(UpdateFAOtoFSWClient.java:102)
at fao.UpdateFAOtoFSWClient.main(UpdateFAOtoFSWClient.java:29)

Methode 2

    public void test2() 
    {
        try 
        {
            String serviceName = "UpdateFAOtoFSWService";            
            String servicePort = "UpdateFAOtoFSWServiceHttpSoap12Endpoint";            
            String url = "http://localhost:8041/axis2/services/UpdateFAOtoFSWService";
            
            String namespace = "http://fao";
            Service service = Service.create(new URL(url + "?wsdl") 
                                            ,new QName(namespace , serviceName));
            
            Object proxy = service.getPort(new QName(namespace, servicePort)
                                          ,fao.UpdateFAOtoFSW.class);
            
            ((fao.UpdateFAOtoFSW)proxy).getTables("blupp");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        } 
    }

Ergebnis:

javax.xml.ws.soap.SOAPFaultException: jndi name is not specified
at com.sun.xml.internal.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:214)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:129)
at com.sun.proxy.$Proxy22.getTables(Unknown Source)
at fao.UpdateFAOtoFSWClient.test2(UpdateFAOtoFSWClient.java:126)
at fao.UpdateFAOtoFSWClient.main(UpdateFAOtoFSWClient.java:30)

Methode 3

    public void test3() 
    {
        try 
        {
            String serviceName = "UpdateFAOtoFSWService";            
            String servicePort = "UpdateFAOtoFSWServiceHttpEndpoint";            
            String url = "http://localhost:8041/axis2/services/UpdateFAOtoFSWService";            
            String namespace = "http://fao";
            Service service = Service.create(new URL(url + "?wsdl") 
                                            ,new QName(namespace , serviceName));
            
            Object proxy = service.getPort(new QName(namespace, servicePort)
                                          ,fao.UpdateFAOtoFSW.class);
                        
            BindingProvider bp = (BindingProvider)proxy; 
            bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
            
            ((fao.UpdateFAOtoFSW)proxy).getTables("blupp");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        } 
    }

**Ergebnis: **

javax.xml.ws.soap.SOAPFaultException: jndi name is not specified
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:129)
at com.sun.proxy.$Proxy22.getTables(Unknown Source)
at fao.UpdateFAOtoFSWClient.test3(UpdateFAOtoFSWClient.java:152)
at fao.UpdateFAOtoFSWClient.main(UpdateFAOtoFSWClient.java:31)

In der 3. Methode bekomme ich die gleiche Exception wie in Methode2, obwohl ich den ServicePort aus Methode1 verwende.

Nun stellt sich mir die Frage, wie kann ich den JNDI für mein Web-Service einrichten oder spezifizieren. Dies muss ich bei der Nutzen des Glassfish nicht machen.


#3

Ich kann die Methoden meines Web-Service noch nicht nutzen, wie oben beschrieben, aber ich kann mit folgenden Code mein Web-Service voll nutzen, wenn er auf dem Glassfish oder dem JBoss läuft.

public void test()
    {
        try {
            String serviceName = "UpdateFAOtoFSWService";
            String servicePort = "UpdateFAOtoFSWPort";
            String url = "http://localhost:8061/UpdateFAOtoFSW/UpdateFAOtoFSWService/DefaultUpdateFAOtoFSW";
            String namespace = "http://fao";
            Service service = Service.create(new URL(url + "?wsdl") , new QName(namespace , serviceName));           
            
            Object proxy = null;
            try {
                proxy = service.getPort(fao.UpdateFAOtoFSW.class);            
            }
            catch(Exception e)
            {
                proxy = service.getPort(new QName(namespace, servicePort),fao.UpdateFAOtoFSW.class);
            }
            
            BindingProvider bp = (BindingProvider)proxy;             
            bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
            /*bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
            bp.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY,new Boolean("true"));
            bp.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY,"ns:getTablesRequest");
            
            bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "admin");
            bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "axis2");
            bp.getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY, new Boolean("true"));
            */
            
            
            if(!bp.getRequestContext().isEmpty())
            {
                for(int index = 0; index < bp.getRequestContext().keySet().toArray().length; index++)
                {
                    System.out.println(bp.getRequestContext().keySet().toArray()[index].toString() + " : " 
                                     + bp.getRequestContext().get(bp.getRequestContext().keySet().toArray()[index].toString()));
                }
            }      
            
            System.out.println(((fao.UpdateFAOtoFSW)proxy).getTables("test"));
        }
        catch(Exception e) 
        {
            e.printStackTrace();
        }
    }

Grundsätzlich muss man wissen, wenn im Tag @WebService die Parameter serviceName und/oder portName nicht gesetzt werden, dann werden als Defaultwerte dem Namen des Interfaces(falls kein Interface vorhanden, der Klassenname) die Zeichenkette “Service” und “Port” angehangen. In meinem Fall also :
Service-Name: UpdateFAOtoFSWService
Port-Name : UpdateFAOtoFSWPort

Kleine Nebeninfo zum JBoss:
Sämtliche Informationen zum Service habe ich nur in der Console nach dem Deployen gefunden. Die mir fehlende Url zu meinem Service, fand ich unter
“JBoss Web Services Console” >> “View a list of deployed services”.
Ob sich irgendwie noch mehr Informationen anzeigen lassen, weiß ich leider nicht. jemand dazu noch was weiß, wäre ich über Informationen sehr dankbar. Zumal es viele offene Threads mit diesem Thema gibt.


#4

Hallo,

ich bekomme bei meiner web.xml folgende Fehlermeldung beim deployen im JBoss:

**The declaration for the entity “HTML.Version” must end with ‘>’. **

[XML]

<display-name>WebTestService</display-name>
<description>Ein ganz einfacher WebService</description>

<servlet>
   <servlet-name>WebTestService</servlet-name>
    <display-name>WebTestService</display-name>
    <description>Servlet Beschreibung</description>
     <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>WebTestService</servlet-name>
    <url-pattern>/WebTestService2</url-pattern>
</servlet-mapping>

<listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>

<session-config>
    <session-timeout>
        30
    </session-timeout>
</session-config>
[/XML]

Kommentiere ich das zweite web-app Start-Tag ein, so bekomme ich diesen Fehler nicht mehr, aber dann kann ich bei keine etc. angeben.

Die vollständige Fehlermeldung vom JBoss:

Failed to create Resource WebTest.war - cause: java.lang.Exception:Failed to start deployment [vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war] during deployment of ‘WebTest.war’ - cause: java.lang.RuntimeException:org.jboss.deployers.client.spi.IncompleteDeploymentException: Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS): *** DEPLOYMENTS IN ERROR: Name -> Error vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war -> org.jboss.deployers.spi.DeploymentException: Error creating managed object for vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war DEPLOYMENTS IN ERROR: Deployment “vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war” is in error due to the following reason(s): org.jboss.xb.binding.JBossXBRuntimeException: -1:-1 31:3 The declaration for the entity “HTML.Version” must end with ‘>’. -> org.jboss.deployers.client.spi.IncompleteDeploymentException:Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS): *** DEPLOYMENTS IN ERROR: Name -> Error vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war -> org.jboss.deployers.spi.DeploymentException: Error creating managed object for vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war DEPLOYMENTS IN ERROR: Deployment “vfs:///home/seann/Programme/jboss-6.1.0.Final/server/default/deploy/WebTest.war” is in error due to the following reason(s): org.jboss.xb.binding.JBossXBRuntimeException: -1:-1 31:3 The declaration for the entity “HTML.Version” must end with ‘>’.