JAX-WS Web service on Tomcat without sun-jaxws.xml

14,172

Solution 1

Sadly, the configuration must exist somewhere. That is mandatory, per the source. Believe it or not, the location of the sun-jaxws.xml file is hard-coded to /WEB-INF/sun-jaxws.xml (thanks, guys @ Metro).

Effectively, you need to take control of the following classes


What needs to happen:

  1. WSServletContextListener will obviously not be extended. This listener performs most of the initializations per the sun-jaxws.xml and jaxws-catalog file. Like I mentioned earlier, the location is hard coded. So your path of least resistance here is to

    • implement your own vanilla servlet listener (with @WebListener) and call a new WSServletContextListener(). You'll then delegate your own contextInitialized(ServletContext ctxt) and contextDestroyed() methods to the ones in your instance of WSServletContextListener.

    • Generate the file on instantiation of the listener, on the fly, using an @XmlRootElement class that'll represent the sun-jaxws file(I'll provide a sample of this in a short while, don't have the time right now :) ).

It's a lot of trouble for such a dispensable convenience, IMO, but it should work in theory. I'll write some samples and see how they play shortly.

Solution 2

To have JAX-WS support in Tomcat you must configure:

  • WEB-INF/sun-jaxws.xml
  • WSServletContextListener
  • WSServlet

Unfortunately it is hard to omit the WEB-INF/sun-jaxws.xml file but there is easier way to omit web.xml configuration because of Servlet 3.0 API.

You can do something like this:

@WebServlet(name = "ServiceServlet" , urlPatterns = "/service", loadOnStartup = 1)
public class Servlet extends WSServlet {

}

and

@WebListener
public class Listener implements ServletContextAttributeListener, ServletContextListener {

    private final WSServletContextListener listener;

    public Listener() {
        this.listener = new WSServletContextListener();
    }

    @Override
    public void attributeAdded(ServletContextAttributeEvent event) {
        listener.attributeAdded(event);
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {
        listener.attributeRemoved(event);
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
        listener.attributeReplaced(event);
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        listener.contextInitialized(sce);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        listener.contextDestroyed(sce);
    }
}

I have tested it on Tomcat-8.5.23 version and it works. But remember that you still must have WEB-INF/sun-jaxws.xml file.

<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
       version="2.0">
    <endpoint name="SampleService"
          implementation="com.ws.ServiceImpl"
          url-pattern="/service" />
</endpoints>

Solution 3

I have publised web services successfully by this way. I have used apache cfx for publishing in servletContextListener.

@WebListener
public class WebServicePublisListener implements ServletContextListener {

    /**
     * Default constructor. 
     */
    public WebServicePublisListener() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent sce)  { 
        JaxWsServerFactoryBean srvFactory = new JaxWsServerFactoryBean();
        srvFactory.setServiceClass(RandService.class);
        srvFactory.setAddress("/RandService");
        srvFactory.setServiceBean(new RandServiceImplement());
        srvFactory.create();
    }

Solution 4

You have to publish the web service. You can implement a ServletContextListener and publish the endpoint:

@javax.servlet.annotation.WebListener 
public class AppServletContextListener implements javax.servlet.ServletContextListener {

    public void contextInitialized(ServletContextEvent sce) { 
        Endpoint.publish("{protocol}://{host}:{port}/{context}/{wsName}", new MyHelloWorldWSImpl());
    } 

    public void contextDestroyed(ServletContextEvent sce) { 
        .... 
    }
}

sun-jaxws.xml is not mandatory by specs...If you note, for example, glassfish (metro) makes it optional. Also, if you expose a EJB 3.1 as webservice (with jaxws) you can see no sun-jaxws.xml file in the generated build.

Share:
14,172

Related videos on Youtube

Miljen Mikic
Author by

Miljen Mikic

Math &amp; problem solving lover. Software development engineer with considerable experience in Linux and database worlds. Holding MSc in Computer Science and PhD in Mathematics. Some answers that I learnt a lot from: BalusC's Using java.net.URLConnection to fire and handle HTTP requests templatetypedef's What is pseudopolynomial time? How does it differ from polynomial time? Mystical's Why is processing a sorted array faster than an unsorted array? Some answers that I am proud of: How to calculate smallest multiple formed only of the digit 1? How to calculate smallest number with certain number of divisors? Java EE Containers vs Web Containers

Updated on September 28, 2022

Comments

  • Miljen Mikic
    Miljen Mikic over 1 year

    I am trying to minimize required configuration while deploying JAX-WS-based Web service on Tomcat. With the introduction of Servlet 3.0 (supported by Tomcat 7+), web.xml can be thrown out, but there is still sun-jaxws.xml. This blog post is interesting:

    Of course, with the use of jax-ws annotations, even configuration sun-jaxws.xml can be made optional making it completely descriptor free, but that requires specifying a default url-pattern like in JSR-109 or custom pattern like in Jersey REST services, in the JAX-WS specification.

    Is it possible to avoid sun-jaxws.xml on Tomcat, and how?

  • Miljen Mikic
    Miljen Mikic almost 11 years
    Thanks for the answer. However, I don't want to use Endpoint.publish(..) infrastructure because it represents a lightweight HTTP server - if I wanted that, I wouldn't have used Tomcat. Next, Tomcat is a servlet container; in other words you cannot deploy EJBs on Tomcat. I'm aware that works like a charm in Glassfish, but that's because Glassfish is JSR-109-compliant.
  • Michael Henrique
    Michael Henrique almost 11 years
    Tomcat does not supports EJB by default. You should consider using, for instance, TomEE. I mentioned EJB just to act as a example to demonstrate no needs of sun-jaxws.xml (It's not mandatory).
  • Miljen Mikic
    Miljen Mikic almost 11 years
    Personally, I would always prefer full application server (such as Glassfish) over servlet container (such as Tomcat). But, our clients use Tomcat and I am curious if it's possible to simplify a configuration needed for the deployment of Web services on Tomcat. Therefore, my question is specifically about Tomcat, not TomEE or Glassfish.
  • Miljen Mikic
    Miljen Mikic almost 11 years
    +1, didn't know that the location of sun-jaxws.xml is hard-coded :) What about default url-pattern that should make sun-jaxws.xml optional (see the blog I have cited in my question), do you know anything about it?
  • kolossus
    kolossus almost 11 years
    @MiljenMikic reading that post carefully, it all seems like a lot of wishful thinking and not much of a reference: The link in his blog post is dead. I still managed to track down the sources he was referring to here and the readme.txt still indicates a sun-jaxws.xml is necessary
  • Miljen Mikic
    Miljen Mikic almost 9 years
    Thanks for the answer. I should have tagged my question with "JAX-WS RI" or "Metro" tags, since sun-jaxws.xml is related to these implementations. Apache CXF is different implementation of JAX-WS, so it does not have nothing with sun-jaxws.xml.
  • Miljen Mikic
    Miljen Mikic over 6 years
    I am aware that we can omit web.xml file, that is already mentioned in the text of the question. The question is about omitting sun-jaxws.xml file.
  • Adrian Malik
    Adrian Malik over 6 years
    Ahh okay but I added the solution for other people that might not know how to omit web.xml file for this problem. For example I had that problem several weeks ago.
  • user1887464
    user1887464 over 2 years
    is there any way we can specify port in this xml configuration ?