Tuesday, February 17, 2009

JAX-WS: How to configure the service end point at runtime?


When deploying your Web Service client you often need to change the endpoint of the service that  has been set during the code generation. This short post explains how you can set change it at runtime in the client code.

You have two approaches to do that:

  • set the endpoint in the Port using the BindingProvider
  • get the endpoint URL from the WSDL itself at runtime

Use the Binding Provider to set the endpoint URL

The first approach is to change the BindingProvider.ENDPOINT_ADDRESS_PROPERTY property value of the BindingProvider (Port) using the following code:
        try { 
           
EmployeeServiceService service = new EmployeeServiceService();
           
EmployeeService port = service.getEmployeeServicePort();

           
BindingProvider bp = (BindingProvider)port;
           
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://server1.grallandco.com:8282/HumanRessources/EmployeeServiceService");

           
Employee emp = port.getEmployee(123);



           
System.out.println("Result = "+ emp);
       
} catch (Exception ex) {...

          

Use the WSDL to get the endpoint URL

Another part is to set the WSDL when you are creating the Service. The service will be using the value that is located in the WSDL port -SOAP Endpoint-. This is simply done using the following code:
        try { 
          
EmployeeServiceService service =
          
new org.demo.service.EmployeeServiceService
               
(new URL("http://server1.grallandco.com:8282/HumanRessources/EmployeeServiceService?wsdl"),
               
new QName("http://service.demo.org/","EmployeeServiceService"));

           
EmployeeService port = service.getEmployeeServicePort();

           
Employee emp = port.getEmployee(123);

         System.out.println("Result = "+ emp);
       
} catch (Exception ex) {
          

Note that, in Glassfish, like lot of Web Service environments the WSDL can generate dynamically the Endpoint URL based on the URL used  to get the WSDL. With this approach you can also dynamically change the Soap endpoint. (If compatible with the network configuration of the production environment.)

9 comments:

Tony said...

Thanks Tug, that is useful.

Anonymous said...

And when are we going to have the EmployeeServiceServiceService to service that service ?

Tug said...

It is a very simple service that I have created and published in Netbeans 6.5/Glassfish V2. Something like:
----
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package org.demo.service;

import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.NotSupportedException;
import javax.transaction.UserTransaction;
import org.demo.entity.Employee;

/**
*
* @author tgrall
*/
@WebService()
public class EmployeeService {


@PersistenceContext(unitName="HumanRessourcesPU")
private EntityManager em;

@Resource private UserTransaction utx;


/**
* Web service operation
*/
@WebMethod(operationName = "getEmployee")
public Employee getEmployee(@WebParam(name = "id")
Integer id) {
Employee employee = null;
try {
utx.begin();
employee = em.find(Employee.class, id);
utx.commit();
} catch (Exception ex) {
Logger.getLogger(EmployeeService.class.getName()).log(Level.SEVERE, null, ex);
}
return employee;
}


@WebMethod (operationName="createEmployee")
public String createEmployee(Employee employee) throws Exception {
utx.begin();
em.persist(employee);
utx.commit();
return "Employee Created";
}


@WebMethod (operationName="getEmployees")
public List<Employee> getEmployees() {
List results = em.createNamedQuery("Employee.findAll").getResultList();
return results;
}

}
------

With a very simple table Employee created in JavaDB

Anonymous said...

Thank you! Using the Binding Provider to set the endpoint URL is exactly what I was looking for. Often the soap:address is wrong because of load balancers etc.

Mutuelle sante said...

Thanks a ton it has been a great help, now to configure the service end point at runtime? is without a doubt simple and easy with the help of your information. Kudos

Yunnyyy said...

Thanks soooo much you are a half-god and just saved my life :))

Ethan said...

Thanks Tug! What a crappy design, it would have taken me quite a while to figure that out.

Yogesh Gandhi said...

Thanks a lot for creating this post.

This saved a lot of time for me.

I just googled and easily located this post.

Thanks again !!!

Anonymous said...

Really usefull thanks!, lost a whole morning adding ports programatically to my Service (useless for this matter), until i went google and found this.