JAX-WS Change Endpoint Example
In this example, we will demonstrate how to change the service endpoint in a Java web service client application.
1. Introduction
A web service (which is described in a WSDL file) can have one or more endpoints. A web service endpoint is a URL used to locate and access a web service. The endpoint is derived from the port and binding elements of the WSDL and is defined in the service element. Web service clients use endpoints to access and invoke operations on a service.
There are several techniques that can be used to invoke web service operations by Java client applications. One common method is to use the ‘wsimport’ command-line tool (part of the Java SE) to generate the client code.
The ‘wsimport’ tool generates artifacts based on the WSDL of the target web service. The artifacts include stubs that function as proxies for accessing the web service, which is typically running on another computer.
The endpoint URL is hard-coded in the generated Service class (described in the example below). There are times when the endpoint of web service has changed, and you don’t have access to the WSDL in order to regenerate the client code. In this example, we will show how to change the service endpoint in a client application by using a Service class constructor.
1.1 Tools Used in this Example
- Eclipse IDE for Enterprise Java Developer 2018-12
- Tomcat 9.0
2. JAX-WS Change Endpoint Example
2.1 Import the Web Service Project
Begin by downloading the Random Quote zip file from the download section. Next, import the Random Quote Project into your workspace with the following steps:
Click File -> Import… and select Projects from Folder or Archive. Click Next.
Click on the Archive… button and select the Random-Quote.zip file. Select the Eclipse project from the list and click Finish.
2.2 Configuring the Service Endpoint
The Random Quote web service was developed using the bottom-up approach. Therefore, we can set the service endpoint URL in a configuration file. Since we are using Apache CXF as the web service stack, we configured the endpoint in the cxf-servlet.xml file. The endpoint is specified in the address attribute of the jaxws:server element.
cxf-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:server id="quoteService" serviceClass="com.javacodegeeks.examples.RandomQuote" address="/getQuote"> <jaxws:serviceBean> <bean class="com.javacodegeeks.examples.RandomQuoteImpl" /> </jaxws:serviceBean> </jaxws:server> </beans>
Note: If we were using the top-down development approach we would configure the endpoint directly in the service element of the WSDL contract.
2.3 Start the Random Quote Web Service
Right-click the project and select Run As -> Run on Server. Select the Tomcat server and click “Finish”. When the application starts, you will see the “Available SOAP services” page.
You will notice that the endpoint address for the RandomQuote service is http://localhost:8080/JaxWsRandomQuote/getQuote. Click on WSDL link to view the WSDL file.
Random Quote WSDL File
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://examples.javacodegeeks.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="RandomQuoteService" targetNamespace="http://examples.javacodegeeks.com/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://examples.javacodegeeks.com/" elementFormDefault="unqualified" targetNamespace="http://examples.javacodegeeks.com/" version="1.0"> <xs:element name="getQuote" type="tns:getQuote"/> <xs:element name="getQuoteResponse" type="tns:getQuoteResponse"/> <xs:complexType name="getQuote"> <xs:sequence/> </xs:complexType> <xs:complexType name="getQuoteResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="getQuoteResponse"> <wsdl:part element="tns:getQuoteResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="getQuote"> <wsdl:part element="tns:getQuote" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:portType name="RandomQuote"> <wsdl:operation name="getQuote"> <wsdl:input message="tns:getQuote" name="getQuote"> </wsdl:input> <wsdl:output message="tns:getQuoteResponse" name="getQuoteResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="RandomQuoteServiceSoapBinding" type="tns:RandomQuote"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getQuote"> <soap:operation soapAction="" style="document"/> <wsdl:input name="getQuote"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="getQuoteResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="RandomQuoteService"> <wsdl:port binding="tns:RandomQuoteServiceSoapBinding" name="RandomQuotePort"> <soap:address location="http://localhost:8080/JaxWsRandomQuote/getQuote"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
You can see that the endpoint URL is defined in the location attribute of the soap:address element. (The WSDL file is generated on-the-fly by the web services stack.)
2.4 Create the Web Service Client
We will create a stand-alone Java client application. Start by creating a Java project for the client code.
- Select New -> Other… In the “Select a wizard” window, select Maven Project from the Maven section and click Next.
- Select “Create a simple project (skip archetype selection)” and click Next.
- Enter a Group Id and Artifact Id. Select “jar” for Packaging and a Name and Description if desired. Click Finish.
2.5 Generate the Web Service Client Code
Next, generate the web service client code:
- Expand the client project, right-click src/main/java and select Show In -> Terminal.
- Copy the web service WSDL URL from your browser. It should look like this: http://localhost:8080/JaxWsRandomQuote/getQuote?wsdl.
- Run the wsimport command (shown below) to generate the client code. (Replace <WSDL_URL> with the one copied from your browser.) Note: The web service must be running when you run the wsimport command.
wsimport -keep -p com.javacodegeeks.examples.client <WSDL_URL>
The wsimport command-line tool is included in the Java SE. The -keep option saves the Java source files and the -p options specifies the Java package we want to use for the generated files.
Running the wsimport command will generate the following files:
- GetQuote.class
- ObjectFactory.class
- RandomQuote.class
- RandomQuoteService.java
- GetQuote.java
- ObjectFactory.java
- RandomQuote.java
- GetQuoteResponse.class
- package-info.class
- GetQuoteResponse.java
- package-info.java
- RandomQuoteService.class
2.6 View the Service Class
Open the RandomQuoteService.java file.
RandomQuoteService.java
package com.javacodegeeks.examples.client;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.9-b130926.1035
* Generated source version: 2.2
*
*/
@WebServiceClient(name = "RandomQuoteService", targetNamespace = "http://examples.javacodegeeks.com/", wsdlLocation = "http://localhost:8080/JaxWsRandomQuote/getQuote?wsdl")
public class RandomQuoteService
extends Service
{
private final static URL RANDOMQUOTESERVICE_WSDL_LOCATION;
private final static WebServiceException RANDOMQUOTESERVICE_EXCEPTION;
private final static QName RANDOMQUOTESERVICE_QNAME = new QName("http://examples.javacodegeeks.com/", "RandomQuoteService");
static {
URL url = null;
WebServiceException e = null;
try {
url = new URL("http://localhost:8080/JaxWsRandomQuote/getQuote?wsdl");
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
RANDOMQUOTESERVICE_WSDL_LOCATION = url;
RANDOMQUOTESERVICE_EXCEPTION = e;
}
public RandomQuoteService() {
super(__getWsdlLocation(), RANDOMQUOTESERVICE_QNAME);
}
public RandomQuoteService(WebServiceFeature... features) {
super(__getWsdlLocation(), RANDOMQUOTESERVICE_QNAME, features);
}
public RandomQuoteService(URL wsdlLocation) {
super(wsdlLocation, RANDOMQUOTESERVICE_QNAME);
}
public RandomQuoteService(URL wsdlLocation, WebServiceFeature... features) {
super(wsdlLocation, RANDOMQUOTESERVICE_QNAME, features);
}
public RandomQuoteService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public RandomQuoteService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
super(wsdlLocation, serviceName, features);
}
/**
*
* @return
* returns RandomQuote
*/
@WebEndpoint(name = "RandomQuotePort")
public RandomQuote getRandomQuotePort() {
return super.getPort(new QName("http://examples.javacodegeeks.com/", "RandomQuotePort"), RandomQuote.class);
}
/**
*
* @param features
* A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features
parameter will have their default values.
* @return
* returns RandomQuote
*/
@WebEndpoint(name = "RandomQuotePort")
public RandomQuote getRandomQuotePort(WebServiceFeature... features) {
return super.getPort(new QName("http://examples.javacodegeeks.com/", "RandomQuotePort"), RandomQuote.class, features);
}
private static URL __getWsdlLocation() {
if (RANDOMQUOTESERVICE_EXCEPTION!= null) {
throw RANDOMQUOTESERVICE_EXCEPTION;
}
return RANDOMQUOTESERVICE_WSDL_LOCATION;
}
}
Notice that the endpoint URL is hard-coded in the static code block (line 32). Also, notice that there are several constructors available to instantiate the RandomQuoteService class
.
2.7 Create the Client Application
Create a Java class with the following code:
RandomQuoteClient.java
package com.javacodegeeks.examples.client; public class RandomQuoteClient { public static void main(String[] args) { RandomQuoteService service = new RandomQuoteService(); RandomQuote port = service.getRandomQuotePort(); System.out.println("Quote of the day: " + port.getQuote()); } }
First, we instantiate a service client class using the RandomQuoteService
no-argument constructor on line 6. We then get the service endpoint interface (SEI) from the service object on line 7. Finally, we send the request and print out the response on line 9.
2.8 Test the Web Service Client
Right-click the Java class and select Run As -> Java Application. You
will see a successful response in the console.
Web Service Client Output
Quote of the day: I think therefore I am
2.9 Modify the Web Service Endpoint
Open cxf-servlet.xml and change the address attribute of the jaxws:server element from /getQuote to /getRandomQuote:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:cxf="http://cxf.apache.org/core" xmlns:soap="http://cxf.apache.org/bindings/soap" xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:server id="quoteService" serviceClass="com.javacodegeeks.examples.RandomQuote" address="/getRandomQuote"> <jaxws:serviceBean> <bean class="com.javacodegeeks.examples.RandomQuoteImpl" /> </jaxws:serviceBean> </jaxws:server> </beans>
Restart the server and reload the web service in your browser.
You will notice that the endpoint has changed. If you run the client now, you will get an exception.
Web Service Client Exception
Exception in thread "main" javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://localhost:8080/JaxWsDepencencies/getQuote?wsdl. It failed with: http://localhost:8080/JaxWsDepencencies/getQuote?wsdl. at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:250) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:194) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:163) at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:348) at com.sun.xml.internal.ws.client.WSServiceDelegate.(WSServiceDelegate.java:306) at com.sun.xml.internal.ws.client.WSServiceDelegate.(WSServiceDelegate.java:215) at com.sun.xml.internal.ws.client.WSServiceDelegate.(WSServiceDelegate.java:196) at com.sun.xml.internal.ws.client.WSServiceDelegate.(WSServiceDelegate.java:192) at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:104) at javax.xml.ws.Service.(Service.java:77) at com.javacodegeekses.client.RandomQuoteServiceService.(RandomQuoteServiceService.java:42) at com.javacodegeekses.client.QuoteClient.main(QuoteClient.java:6) Caused by: java.io.FileNotFoundException: http://localhost:8080/JaxWsDepencencies/getQuote?wsdl at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1890) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492) at java.net.URL.openStream(URL.java:1045) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:984) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:385) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:216) ... 11 more
We are getting an exception
because the no-argument constructor is using the hard-coded value, which is no
longer valid because the web service endpoint has changed. In order to fix this, we will need to modify
the client application.
2.10 Modify the Client
We can use the RandomQuoteService(URL wsdlLocation) constructor to override the hard-coded endpoint Modify the client application by passing in the new endpoint URL to the constructor:
RandomQuoteClient.java
package com.javacodegeeks.examples.client; import java.net.MalformedURLException; import java.net.URL; public class RandomQuoteClient { public static void main(String[] args) throws MalformedURLException { RandomQuoteService service = new RandomQuoteService( new URL("http://localhost:8080/JaxWsRandomQuote/getRandomQuote")); RandomQuote port = service.getRandomQuotePort(); System.out.println("Quote of the day: " + port.getQuote()); } }
If you run the client application again, you will get a successful response.
Web Service Client Output
Quote of the day: It was the best of times, it was the worst of times...
3. Summary
In this post, we demonstrated how to change a web service endpoint in a Java client application.
4. Download the Source Code
This was a JAX-WS Change Endpoint Example.
clean, detailed, good tutorial post