26
May

Web Service clients running in a Java EE container - what can the container do for you when it acts as a web service client?

When your application is a Java EE application, for example, a Web application or an EJB application and you have to communicate with web services the application running inside the container act as a client.

Remember it can also be a client Java EE application and then run on the client container. By running on a client container, it can leverage lots of the things a Java EE application running on a server environment can like, for example, annotations.

Returning to the original subject, when the Java EE application acts as a client of a web service, you can use the @WebServiceRef to inject the reference to the Web Service client. By injecting the reference using annotations, you allow the container to take care of the client and you can leverage the container to make configurations and other stuff declaratively instead of doing that via code.

Bellow we have an example of the injection of a web service reference in a servlet and later usage of the service in the servlet’s code:

package br.com.amadei.blog.servlet;

import java.io.IOException;
import java.io.PrintWriter;

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.ws.WebServiceRef;

import br.com.amadei.blog.ws.HelloWorldService;
import br.com.amadei.blog.ws.HelloWorldServiceService;

@WebServlet("/WsClientServlet")
public class WsClientServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@WebServiceRef(name = "HelloWorldService")
	private HelloWorldServiceService service;

	public WsClientServlet() {
		super();
	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) 
                        throws ServletException, IOException {
		HelloWorldService port = service.getHelloWorldServicePort();

		PrintWriter out = response.getWriter();

		out.println("<h2>");
		out.println("Web Service response: "
				+ port.sayHello(request.getParameter("name")));
		out.println("</h2>");

	}

}

 

Take a closer look at the @WebServiceRef annotation in the code above. Pay attention that such annotation has an attribute name with a string defining it. This string defines the name of the service reference and this name is what we use to link the service reference annotation with its definition in a deployment descriptor.

As the sample application is a web application, the service reference is declared in the weblogic’s web descriptor: weblogic.xml, inside WEB-INF. Bellow we have a sample of this weblogic.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app ...>
    <wls:weblogic-version>12.1.2</wls:weblogic-version>
    <wls:context-root>HelloWorldWebServiceClient</wls:context-root>
    <wls:service-reference-description>
        <wls:service-ref-name>HelloWorldService</wls:service-ref-name>
        <wls:wsdl-url>http://host:port/HelloWorldWebService
           /HelloWorldServiceService?WSDL</wls:wsdl-url>
    </wls:service-reference-description>
</wls:weblogic-web-app>

 

This descriptor already shows something very important about the power that comes with the usage of the application server + annotation + deployment descriptor: you are referencing the WSDL's URL via the XML descriptor, so if you have to change the endpoint to promote the application among different environments, you can do that using the deployment descriptor without touching code or resorting to custom solutions like custom configuration files, custom system properties and so on. To make things even simpler, you can use deployment plans to update such properties so you can do that without touching code:

<?xml version='1.0' encoding='UTF-8'?>
<deployment-plan ...>
  <application-name>HelloWorldWebServiceClient.war</application-name>
  <variable-definition>
    <variable>
      <name>ServiceReferenceDescription_HelloWorldService_WsdlUrl_140050201249438</name>
      <value>http://qaenv:7001/HelloWorld/HelloWorldServiceService?WSDL</value>
    </variable>
  </variable-definition>
  <module-override>
    <module-name>HelloWorldWebServiceClient.war</module-name>
    <module-type>war</module-type>
    <module-descriptor external="false">
      <root-element>weblogic-web-app</root-element>
      <uri>WEB-INF/weblogic.xml</uri>
      <variable-assignment>
        <name>
           ServiceReferenceDescription_HelloWorldService_WsdlUrl_140050201249438
        </name><xpath>/weblogic-web-app/service-reference-description
          /[service-ref-name="HelloWorldService"]/wsdl-url</xpath>
        <origin>planbased</origin>
      </variable-assignment>
    </module-descriptor>
  </module-override>
  <config-root>/app/config/deployments/HelloWorldWebServiceClient.war/plan</config-root>
</deployment-plan>

 

That’s it. I expect this post gave you an overview on how to leverage the application server capabilities, WebLogic’s in the case shown, to configure Web Services clients in a declarative manner and write less code.


free b2evolution skin
3
May

Applying WS Policies to JAX-WS Web Services in WebLogic Server

When developing a JAX-WS web service to be deployed to a WebLogic Server, you can apply WS-Policies to it. WLS ships with some pre-defined policies that you can specify without having to point to some physical policy file. They are already deployed by WLS.

On the other hand, you can define a policy file and apply this file to the Web Service if the ones already present in WLS does not work for you. In this case, you can create a file like the one bellow, to request username token authentication:

<?xml version="1.0"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
 xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512">
 <sp:SupportingTokens>
  <wsp:Policy>
   <sp:UsernameToken
    sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/AlwaysToRecipient">
    <wsp:Policy>
     <sp:WssUsernameToken10 />
    </wsp:Policy>
   </sp:UsernameToken>
  </wsp:Policy>
 </sp:SupportingTokens>
</wsp:Policy>


After you have the policy file, in our case a very simple username token policy, you place it in WEB-INF/policies for Web applications or META-INF/policies for EJB JARs and shared libraries.

Now it’s just a matter of annotating the web service class. You annotate it with weblogic.jws.Policies and weblogic.jws.Policy annotations and specify as the policy uri the policy XML file name as we can see bellow:

package br.com.amadei.ws.secure;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.Policies;
import weblogic.jws.Policy;

@WebService
public class SecureWS {

	@WebMethod
	@Policies( { @Policy(uri = "policy:usernametoken.xml") } )  
	public String sayHello(String name) {
		return "Hello, " + name;
	}

}


After that, you just deploy the application and the policy is added to the Web Service’s WSDL and enforced at runtime.

For more information, plase check the official documentation here.


free b2evolution skin
12
Feb

The danger of importing multiple XSDs from the same namespace

When you define a Web Service interface with WSDLs and XSDs, you need to be careful on the structure of such elements, so I recommend you to avoid at all costs importing more than one XSD from the same namespace.

Importing multiple XSDs from the same namespace is not prohibited by the specification but it’s also not clear how parsers should handle them, so some parsers take only the first import into consideration while others take all of the imports. This is the worst situation ever as for some situations you will face errors and in others it will work.

As an example, take the following WSDL:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://www.example.org/NewWSDLFile/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="NewWSDLFile"
	xmlns:schema="http://www.example.org/schema"
	targetNamespace="http://www.example.org/NewWSDLFile/">

	<wsdl:types>
		<xsd:schema targetNamespace="http://www.example.org/NewWSDLFile/">

			<xsd:import schemaLocation="Schema1.xsd" namespace="http://www.example.org/schema"/>
			<xsd:import schemaLocation="Schema2.xsd" namespace="http://www.example.org/schema"/>
			
			<xsd:element name="NewOperation">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="in" type="schema:MyType1" />
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
			<xsd:element name="NewOperationResponse">
				<xsd:complexType>
					<xsd:sequence>
						<xsd:element name="out" type="schema:MyType2" />
					</xsd:sequence>
				</xsd:complexType>
			</xsd:element>
		</xsd:schema>
	</wsdl:types>

	<wsdl:message name="NewOperationRequest">
		<wsdl:part element="tns:NewOperation" name="parameters" />
	</wsdl:message>

	<wsdl:message name="NewOperationResponse">
		<wsdl:part element="tns:NewOperationResponse" name="parameters" />
	</wsdl:message>

	<wsdl:portType name="NewWSDLFile">
		<wsdl:operation name="NewOperation">
			<wsdl:input message="tns:NewOperationRequest" />
			<wsdl:output message="tns:NewOperationResponse" />
		</wsdl:operation>
	</wsdl:portType>

	<wsdl:binding name="NewWSDLFileSOAP" type="tns:NewWSDLFile">
		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="NewOperation">
			<soap:operation soapAction="http://www.example.org/NewWSDLFile/NewOperation" />
			<wsdl:input>
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>

	<wsdl:service name="NewWSDLFile">
		<wsdl:port binding="tns:NewWSDLFileSOAP" name="NewWSDLFileSOAP">
			<soap:address location="http://www.example.org/" />
		</wsdl:port>
	</wsdl:service>

</wsdl:definitions>


If you validate this WSDL in Eclipse, it validates OK, however if you try to create Java classes to it using wsimport command, it presents some warnings indicating it can't find some of the types. Actually you see that the problems are found on the types of the second XSD imported, showing it was silently ignored by the parser. Bellow we see the warnings:


[WARNING] src-resolve: Cannot resolve the name 'schema:MyType2' to a(n) 'type definition' component.
line 24 of file:/D:/temp/NewWSDLFile.wsdl#types?schema1

[WARNING] src-resolve: Cannot resolve the name 'schema:MyType2' to a(n) 'type definition' component.
line 24 of file:/D:/temp/NewWSDLFile.wsdl#types?schema1

For other parsers it will not be just a warning, but an error that will make it impossible to consume the web service. For example, if you try to validate this WSDL via WS-I basic profile validation tool, it fails indicating it can’t find the types of the second XSDs.

So, all that said, avoid having multiple XSDs from the same namespace imported by another WSDL or XSD or you're going to have some hard times.


free b2evolution skin
29
Dec

What happened to Eclipse’s Generate XML from XSD Schema menu?

Eclipse and Oracle Enterprise Pack for Eclipse have a very helpful option to generate XML from a XSD as we can see bellow:

 

Sometimes, however, this menu just does not appear for a XSD file and this is due to the fact that the XSD file does not have the XML prolog, like the one bellow:

<?xml version="1.0" encoding="UTF-8"?>

 

Adding the prolog back to the XSD file, makes Eclipse treat the file as an XSD again and the Generate > XML File… menu will be back.

When you need to generate a XML from a XSD and the menu isn’t there, it can become an awful situation and this tip will help you to have the menu back.


free b2evolution skin
7
Oct

Defining smart ranges in XSD

Sometimes we need to specify a range in XML and to validate such XML the natural option is to leverage the XSD language for such.

The following XSD illustrates one way to define a range in XSD, where we defined a range of two dates:


<element name="DateRange" type="tns:DateRangeType"/>

<complexType name="DateRangeType">
  <sequence>
   <element name="From" type="date" />
   <element name="To" type="date" />
  </sequence>
</complexType>


 
The approach above is nice but it only works if what you want is always specify the start and end of the range. If your range may allow one of the sides to be omitted, tending to infinity, you will have to specify something like the one bellow:


<element name="DateRange" type="tns:DateRangeType"/>

<complexType name="DateRangeType">
  <sequence>
   <element name="From" type="date" minOccurs="0"/>
   <element name="To" type="date" minOccurs="0"/>
  </sequence>
</complexType>


 
The approach above is also nice but as both elements are optional, an element without From and To will be considered valid but this is something we do not want as in this case, we may omit the parent element at all. Our problem is that this element would be considered valid:


<DateRange/> 


 
We would like to consider an element valid only if contains at least the From, To or both elements. The solution for this dilemma is the following XSD:


<element name="DateRange" type="tns:DateRangeType"/>

<complexType name="DateRangeType">
  <sequence>
   <choice>
    <sequence>
     <element name="From" type="dateTime" />
     <element name="To" type="dateTime" minOccurs="0" />
    </sequence>
    <element name="To" type="dateTime" />
   </choice>
  </sequence>
 </complexType>


 

It may seem complicated at first sight but it’s extremely simple:

The XSD is a choice of one sequence where the element From is mandatory and the element To is optional. So an element of this type with From or From + To would be considered valid. The other part of the choice specifies element To, so an element of this type with only a single To element would also be valid, what covers all of ours requirements.


free b2evolution skin

:: Next >>