TOTD #22: Java SE client for a Metro endpoint

Metro is the Web services stack in GlassFish. It is your one-stop shop from a simple Hello World to Secure, Reliable,  Transactional and .NET 3.0 interoperable endpoint. Metro Tooling is provided by NetBeans and other options are explained here.

Screencast #ws7 describes how a Metro endpoint can be easily created and deployed on GlassFish and invoked from a Web client using NetBeans IDE. This TOTD (as requested here and here) describes how a Secure and Reliable Metro endpoint can be invoked using a Java SE client.

Here is my environment:

Let's get started.

  1. Following screencast #ws7 create a plain (without Reliability and Security enabled) Metro endpoint.
  2. Create the Java SE client project
    1. In NetBeans IDE, create a new project of the type Java/Java Application. Name the project as "SEClient" and take all other defaults.
    2. Right-click on the newly created project, select "New", "Web Service Client...".
    3. Click on the "Browse..." button next to "Project" radio button and select the deployed Web service endpoint.
    4. Enter the package name as "client" and click on "Finish".
  3. Invoke the plain Metro endpoint
    1. Right-click on the project, select "Properties", "Libraries", "Add JAR/Folder" and add "webservices-rt.jar" from the "lib" directory of GlassFish installation. Click on "OK".
    2. Expand the "Web Service References" node in the project and drag the leaf node in the "main" method of "Main.java" of the client project.
    3. Change the value of parameter "name" to "Duke".
    4. Right-click the project and select "Run". This will build the project, invoke the endpoint and show the results in Output window as "Hello Duke".
    5. If your GlassFish instance is configured to show SOAP messages then the following SOAP messages will be shown in the output window:

      ====[com.sun.xml.ws.assembler.server:request]====
      <?xml version="1.0" ?>
      <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
        <S:Body>
          <ns2:sayHello xmlns:ns2="http://server/">
            <name>Duke</name>
          </ns2:sayHello>
        </S:Body>
      </S:Envelope>
      ============
      ====[com.sun.xml.ws.assembler.server:response]====
      <?xml version="1.0" ?>
      <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
        <S:Body>
          <ns2:sayHelloResponse xmlns:ns2="http://server/">
            <return>Hello Duke</return>
          </ns2:sayHelloResponse>
        </S:Body>
      </S:Envelope>
      ============
  4. Invoke the Reliable Metro endpoint
    1. Following the instructions in screencast #ws7, enable Reliability on Metro endpoint and re-deploy.
    2. In the client project, select the first child node of "Web Service References", right-click and select "Refresh Client".
    3. In the "Confirm Client Refresh" window, select "Also replace local wsdl file with original WSDLs located at:" checkbox and click on "Yes".
    4. Right-click the client project and select "Run". This will build the project, invoke the endpoint and show the results in Output window as "Hello Duke".
    5. The SOAP messages during this run will now contain Reliable Messaging protocol messages and resemble as shown below:

      ====[com.sun.xml.ws.assembler.server:request]====
      <?xml version="1.0" ?>
      <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
        <S:Header>
          <To xmlns="http://www.w3.org/2005/08/addressing">http://localhost:8080/SEEndpoint/HelloServiceService</To>
          <Action xmlns="http://www.w3.org/2005/08/addressing">http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</Action>
          <ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
            <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
          </ReplyTo>
          ...
  5. Invoke the Secure Metro endpoint
    1. Following the instructions in screencast #ws7, disable Reliability and enable Security on Metro endpoint and re-deploy.
    2. In the client project, select the first child node of "Web Service References", right-click and select "Refresh Client".
    3. In the "Confirm Client Refresh" window, select "Also replace local wsdl file with original WSDLs located at:" checkbox and click on "Yes".
    4. Right-click on the first child of "Web Service References" node, select "Edit Web Service Attributes" and select "Use development defaults". This will ensure that client and endpoint security credentials match.
    5. Expand "Source Packages", "META-INF" and open "HelloServiceService.xml". The name of this file is derived from the service name at the endpoint and may be different. Specify the location of trust store by adding the following attributes to "sc:KeyStore" element:

      location="C:\\testbed\\glassfish\\final\\glassfish\\domains\\domain1\\config\\cacerts.jks" type="JKS" storepass="changeit"

      The updated element looks like:

      <sc:TrustStore wspp:visibility="private" peeralias="xws-security-server" location="C:\\testbed\\glassfish\\final\\glassfish\\domains\\domain1\\config\\cacerts.jks" type="JKS" storepass="changeit"/>

      Make sure to match the value of location and password of the trust store in your environment.
    6. Right-click the client project and select "Run". This will build the project, invoke the endpoint and show the results in Output window as "Hello Duke".
    7. The SOAP messages during this run are now secured using the default security profile in NetBeans. The SOAP messages resemble as shown below:

      ====[com.sun.xml.ws.assembler.server:request]====
      <?xml version="1.0" ?>
      <S:Envelope
        xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
        xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
        xmlns:exc14n="http://www.w3.org/2001/10/xml-exc-c14n#">
        <S:Header>
          <To xmlns="http://www.w3.org/2005/08/addressing" wsu:Id="5006">http://localhost:8080/SEEndpoint/HelloServiceService</To>
          <Action xmlns="http://www.w3.org/2005/08/addressing" wsu:Id="5005">http://server/HelloService/sayHelloRequest</Action>
          <ReplyTo xmlns="http://www.w3.org/2005/08/addressing" wsu:Id="5004">
            <Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
          </ReplyTo>
          <MessageID xmlns="http://www.w3.org/2005/08/addressing" wsu:Id="5003">uuid:bb0e9571-a773-49bb-bad0-20a01d3af9f1</MessageID>
          <wsse:Security S:mustUnderstand="1">
            <wsu:Timestamp xmlns:ns10="http://www.w3.org/2003/05/soap-envelope" wsu:Id="3">
            <wsu:Created>2008-01-23T20:13:28Z</wsu:Created>
            ...

If you are using JDK version prior to Java SE 6 U4, then need to override the JAX-WS and JAXB API as described here. Java SE 6 U4 already includes JAX-WS and JAXB 2.1 APIs which are required for the Metro client to work.

Please leave suggestions on other TOTD that you'd like to see. A complete archive is available here.

Technorati: totd webservices metro glassfish netbeans javase

Comments:

Hello Arun, I developed a secure service with Netbeans 6.0 and Glassfish v2, but the server certificate expired, now I'am using Netbeans 6.1 and Glassfish v2ur2, but the service only funcions with no security using the old webservices-rt.jar file, when I use the new library a java.lang.NoSuchMethodError appears. May you help me to correct this issue?

Posted by Javier Imbús on August 12, 2008 at 08:10 AM PDT #

Javier,

Can you explain "old webservices-rt.jar" ? Are you using UR2 for development & deployment or a mix/match ?

What version of JDK are you using ?

Posted by Arun Gupta on August 12, 2008 at 10:20 AM PDT #

Here is my envoirment:

Windows XP
Netbeans 6.1
Glassfish v2
Java re 1.6.0_07
Java dk 1.6.0_05

I'm having a problem when invoking my secured webservice from a SE client.

I have a webservice called FrontendWS.
On my FrontendWS I have selected "secured webservice" and "use development defaults" and I have redeployed the webservice.

When I refrence my FrontendWS from a webapplication or any application running on the server I can without problem "communicate" with the FrontendWS.

But when I call my FrontendWS from a SE client it seams to not include the security header in the soap-messages. So I get this errormessage trying to invoke the FrontendWS from FrontendTestClient-se:

Exception caught in FrontendTestClient.Main.login
javax.xml.ws.soap.SOAPFaultException: ERROR: No security header found in the message

Do you have any idea why the SE client does not include a security-header in the SOAP-request?

Posted by Vegard Gillestad on September 28, 2008 at 10:16 PM PDT #

Hi,
first thing you should check is whether you have the full METRO library on JavaSE project's classpath.
NetBeans does not add it automatically - it does add JAX-WS only. So remove JAX-WS 2.1 library from project, then create new METRO library (you can use jars from GlassFish) and add it to the project.

Posted by Martin Grebac on September 29, 2008 at 03:28 PM PDT #

I'm using Sun App server 9.0. I'm not using Netbeans.

I enabled message security for my web service following the instructions in:
http://blogs.sun.com/swchan/entry/troubleshooting_jaxws_message_level_security

I have a Java SE client (whose classpath includes appserv-rt.jar and javaee.jar from Glassfish).

When it connects, the service complains that no security header was found. So, apparently message security on the web service is set up correctly.

But ... how do I get the web service to send encrypted SOAP messages? I'm guessing that I somehow need to point the client at the cacerts.jks. Could you tell me which configuration file and what it needs to contain?

Posted by Lak on October 22, 2008 at 07:54 PM PDT #

Hi,
I believe your problems are in the classpath. You need to put all the metro jars to classpath (webservice\*.jar from GF, or download metro binary distribution directly from metro.dev.java.net).
MartinG

Posted by Martin Grebac on October 23, 2008 at 12:56 AM PDT #

Martin, thanks for the suggestion.

I'm looking in the Glassfish lib folder and I don't see any webservice\*.jar. What I did find was a appserv-ws.jar, so I added it ot the classpath so that I ended up with the following jars from the GF lib folder in the classpath of the Java SE client:

appserv-admin.jar
appserv-rt.jar
appserv-ws.jar
javaee.jar
toplink-essentials-agent.jar
toplink-essentials.jar

The Java SE client still does not send out encrypted SOAP messages. Just for kicks, I tried including every jar file from GF. Still doesn't work. So it is probably not a classpath problem.

However, while digging around, I noticed something odd:

In the sun-web.xml for the web service, I added a message element so that only one of the methods of the web service requires message -level security. The Java SE client is able to call all other methods, except the one that is secured. However, even though the web service is looking for encrypted messages, the WSDL generated by the web service (by adding ?wsdl to the URL: this is what the client code was generated from) does not have any security policy elements ... so how is the client supposed to know that it should send out encrypted messages for one method call and not for the other?

Here is more detail:

sun-web.xml for the web service:
<sun-web-app error-url="">

<servlet>
<servlet-name>CurrencyConverter</servlet-name>
<webservice-endpoint>
<port-component-name>CurrencyConverter</port-component-name>
<endpoint-address-uri>
/CurrencyConverterService
</endpoint-address-uri>
<message-security-binding auth-layer="SOAP"
provider-id="ServerProvider">
<message-security>
<message>
<java-method>
<method-name>getConversionRate</method-name>
</java-method>
</message>
<request-protection auth-source="content" />
<response-protection auth-source="content" />
</message-security>
</message-security-binding>
</webservice-endpoint>
</servlet>

</sun-web-app>

The web service itself was generated from Java by adding @WebService to a POJO. I created a war and deployed it into GF. The deployed war does not have a web.xml, so it should be JSR 109-compliant.

The WSDL that was imported to create the Java SE client was at: http://localhost:8080/${appname}/CurrencyConverterService?wsdl
and looks like this (note the absence of security policy elements):

<types>
<xsd:schema>
<xsd:import namespace="http://forex.gdr.com/" schemaLocation="http://localhost:8080/gdr/CurrencyConverterService/__container$publishing$subctx/WEB-INF/wsdl/CurrencyConverterService_schema1.xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>
</xsd:schema>
</types>
<message name="getConvertedAmount">
<part name="parameters" element="tns:getConvertedAmount"/>
</message>

<message name="getConvertedAmountResponse">
<part name="parameters" element="tns:getConvertedAmountResponse"/>
</message>
<message name="CurrencyInformationUnavailableException">
<part name="fault" element="tns:CurrencyInformationUnavailableException"/>
</message>
<message name="getConversionRate">
<part name="parameters" element="tns:getConversionRate"/>
</message>

<message name="getConversionRateResponse">
<part name="parameters" element="tns:getConversionRateResponse"/>
</message>
<portType name="CurrencyConverter">
<operation name="getConvertedAmount">
<input message="tns:getConvertedAmount"/>
<output message="tns:getConvertedAmountResponse"/>
<fault name="CurrencyInformationUnavailableException" message="tns:CurrencyInformationUnavailableException"/>
</operation>

<operation name="getConversionRate">
<input message="tns:getConversionRate"/>
<output message="tns:getConversionRateResponse"/>
<fault name="CurrencyInformationUnavailableException" message="tns:CurrencyInformationUnavailableException"/>
</operation>
</portType>
<binding name="CurrencyConverterPortBinding" type="tns:CurrencyConverter">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="getConvertedAmount">

<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
<fault name="CurrencyInformationUnavailableException">
<soap:fault name="CurrencyInformationUnavailableException" use="literal"/>

</fault>
</operation>
<operation name="getConversionRate">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>

</output>
<fault name="CurrencyInformationUnavailableException">
<soap:fault name="CurrencyInformationUnavailableException" use="literal"/>
</fault>
</operation>
</binding>
<service name="CurrencyConverterService">
<port name="CurrencyConverterPort" binding="tns:CurrencyConverterPortBinding">
<soap:address location="http://localhost:8080/gdr/CurrencyConverterService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"/>

</port>
</service>
</definitions>

Posted by Lak on October 23, 2008 at 10:18 AM PDT #

If you don't have any webservices-rt.jar in your GF, that means you don't have any Metro installed there. You may find more info on http://metro.dev.java.net

Posted by Martin Grebac on October 29, 2008 at 01:40 AM PDT #

I upgraded to Java SE 6 Update 10 with Glassfish (Earlier I was using Update 3). Now, there is a webservices-rt.jar and webservices-tools.jar in the c:\\sun\\sdk\\lib folder. I added these to the classpath of the Java SE client.

However, I still get the following exception:

com.sun.enterprise.security.jauth.AuthException: Message does not conform to configured policy [ TimestampPolicy(P) ]: No Security Header found

Posted by Lak on October 29, 2008 at 02:37 AM PDT #

I downloaded NetBeans 6.1 to see if I could get it to work and copy the resulting configuration files over to my Eclipse project. I installed NetBeans, then linked it to my existing GF installation (using Tools | Servers). I am able to deploy, undeploy etc. without any problem.

I am also able to set up a web service with a security profile. However, for the Java SE client, I am unable to select the "Use development defaults" checkbox. If I run inspite of not being able to select that checkbox, I get an error:

SEVERE: WSSPIPE0016: TrustStore URL was obtained as NULL from ConfigAssertion.

I don't think this set of instructions works any longer. For the record, I am using Java SE 6 Update 10, the bundled Glassfish app server and Netbeans 6.1

Posted by Lak on October 29, 2008 at 01:11 PM PDT #

Hi Arun,

We have developed RM Project using NetBeans and Glassfish.
Is it possible to migrate that project to BEA/ORacle workshop?

I appreciate your reply.

Thank you

Posted by amar on December 18, 2008 at 11:22 PM PST #

You can use GlassFish for deployment. Why do you want to migrate to Oracle ? :)

Posted by Arun Gupta on December 19, 2008 at 01:03 AM PST #

Dear Arun,

I am trying to build a Java SE client for a service using transport security (SSL).
Following the Java WSIT Tutorial, I am able to build a client based on a servlet and it is working. instead the Java SE one is not working. I have set the right libraries but i get the following fault ( i just attached the first lines of the SOAP body of the response that i got):
<S:Body>
<S:Fault xmlns:ns3="http://www.w3.org/2003/05/soap-envelope" xmlns="">
<faultcode xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">wsse:InvalidSecurity</faultcode>
<faultstring>WSS1601: Security Requirements not met - Transport binding configured in policy but incoming message was not SSL enabled</faultstring>
<detail>

Thanks!

Posted by Francesco Sottini on December 30, 2008 at 03:39 AM PST #

Francesco, please post your question to users@metro.dev.java.net for a quicker response.

Posted by Arun Gupta on January 05, 2009 at 05:52 AM PST #

Hi Arun, hi Lak,

I have a comparable problem with clients, who do not send out encrypted SOAP messages.
My IDE is NetBeans 6.5 with Glassfish V2U1, the libs are added to the classpath.
First I have created a NetBeans-WebProject with a Web Service-Client-Servlet and it works fine,
the servlet sends security SOAP-Header.

But also I have tried a J2ME JSR-172 mobile Client with the same wsdl-file to connect to a security Web Services over SSL, no encrypted SOAP messages are send.

The same problem comes up, when I have created a simple Java-Project, main-Class, no encrypted SOAP messages are send.

Do you have an idea to solve this problem, that the client send out encrypted SOAP messages?

Regards,
Thorsten

Posted by Thorsten on February 17, 2009 at 08:39 PM PST #

Hi Arun,

first problem is solved, with a new netbeans-project and all metro-libs, the java-WS-Client-Application works.

The problem is now the mobile Client.

Is it generally possible to create a J2ME (JSR-172)-Client to communicate over SSL with a security Web Service that is installed on a glassfish-server?

Which metro-libs has to be added to the J2ME-Project?

Regards,
Thorsten

Posted by Thorsten on February 17, 2009 at 11:00 PM PST #

Thorsten,

Please ask your question on users@metro.dev.java.net for a wider audience.

Thanks,
-Arun

Posted by Arun Gupta on February 25, 2009 at 04:58 AM PST #

That's hit.

one thing blocked me is that I added metro library(build in the NB) to the client project library path, instead of jars in the GF install path.

Posted by Azuryy on August 31, 2009 at 07:34 PM PDT #

Hi Arun,

Iam new to webservice,Even though i created a webservice between .net and java.Here java is a client.When i invoked a method from .net to java it throws "error no security header found in the message".Please let me clear what is the solution and i want to do to clear the solution.Please reply me asap.

Posted by guest on June 30, 2011 at 03:30 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today