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

4

14

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?

Epictetus answered 14/5, 2013 at 7:54 Comment(0)
M
15

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.

Munafo answered 22/5, 2013 at 22:11 Comment(2)
+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?Epictetus
@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 necessaryMunafo
C
4

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>
Convert answered 27/11, 2017 at 9:3 Comment(4)
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.Epictetus
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.Convert
is there any way we can specify port in this xml configuration ?Orthodox
what is implementation="com.ws.ServiceImpl" in this example?Baby
R
2

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();
    }
Revamp answered 3/6, 2015 at 11:51 Comment(1)
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.Epictetus
M
1

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.

Microsurgery answered 22/5, 2013 at 1:17 Comment(3)
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.Epictetus
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).Microsurgery
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.Epictetus

© 2022 - 2024 — McMap. All rights reserved.