SOAP WSDL not generating - web-services

I am new to SOAP Web Services and developed a basic application. While running the application it runs fine. When I am trying to see the WSDL file by appending ?wsdl at end of the URL but it does show an error.
I have even tested the same with SOAP UI but it throws an error:
WSDLException (at /html): faultCode=INVALID_WSDL: Expected element '{http://schemas.xmlsoap.org/wsdl/}definitions'.
Below is the code:
package com.WS.Book;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService
public class BookDetails {
#WebMethod
public List<String> getBook() {
List<String> list = new ArrayList();
list.add("Book 1");
list.add("Book 2");
list.add("Book 3");
return list;
}
}
Please do let me know where am I going wrong.

Related

Start embedded Jetty using WebApplicationInitializer

I am creating Restful (Jax-RS) services to be deployed to Fuse 6.2.1.
(using Apache CFX, and deploying with OSGi bundles to Karaf)
The server supports only up to Spring 3.2.12.RELEASE.
I am attempting to do everything with next to zero XML configuration.
So far so good, everything is working and I can deploy and run my services.
However, I'd like to be able to test my services locally without having to deploy them. So I'd like to be able to boostrap a webserver and register my servlet, but can't quite figure our how.
I'm configuring the servlet with this (using Spring's WebApplicationInitializer rather than web.xml):
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
public class CxfServletInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(new ContextLoaderListener(createWebAppContext()));
addApacheCxfServlet(servletContext);
}
private void addApacheCxfServlet(ServletContext servletContext) {
CXFServlet cxfServlet = new CXFServlet();
ServletRegistration.Dynamic appServlet = servletContext.addServlet("CXFServlet", cxfServlet);
appServlet.setLoadOnStartup(1);
Set<String> mappingConflicts = appServlet.addMapping("/*");
}
private WebApplicationContext createWebAppContext() {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(CxfServletConfig.class);
return appContext;
}
}
And my main Spring config looks like this:
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.RuntimeDelegate;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
#Configuration
public class CxfServletConfig {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CxfServletConfig.class);
#Bean(destroyMethod = "shutdown")
public SpringBus cxf() {
return new SpringBus();
}
#Bean
#DependsOn("cxf")
public Server jaxRsServer(ApplicationContext appContext) {
JAXRSServerFactoryBean endpoint = RuntimeDelegate.getInstance().
createEndpoint(jaxRsApiApplication(), JAXRSServerFactoryBean.class);
endpoint.setServiceBeans(Arrays.<Object> asList(testSvc()));
endpoint.setAddress(endpoint.getAddress());
endpoint.setProvider(jsonProvider());
return endpoint.create();
}
#Bean
public Application jaxRsApiApplication() {
return new Application();
}
#Bean
public JacksonJsonProvider jsonProvider() {
return new JacksonJsonProvider();
}
#Bean(name = "testSvc")
public TestService testSvc() {
return new TestService();
}
So just to be clear, the above code is my current, working, deployable configuration. So now I'd like to create a test config that utilizes the same but which also starts Jetty and registers my servlet, and can't quite figure out how. Any help?
Thanks!
EDIT: Turns out I did not need the WebApplicationInitializer at all to get this to work. I ended up creating a Test config for Spring that defines a Jetty server as a bean. Seems to work:
#Configuration
public class TestingSpringConfig {
#Bean (name="jettyServer", destroyMethod = "stop")
public Server jettyServer() throws Exception {
Server server = new Server(0); //start jetty on a random, free port
// Register and map the dispatcher servlet
final ServletHolder servletHolder = new ServletHolder( new CXFServlet() );
final ServletContextHandler context = new ServletContextHandler();
context.setContextPath( "/" );
//fuse uses cxf as base url path for cxf services, so doing so as well here so urls are consistent
context.addServlet( servletHolder, "/mybaseurl/*" );
context.addEventListener( new ContextLoaderListener() );
context.setInitParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );
//this will load the spring config for the CFX servlet
context.setInitParameter( "contextConfigLocation", CxfServletConfig.class.getName() );
server.setHandler( context );
server.start();
//server.join(); if running from a main class instead of bean
return server;
}
#Bean(name = "jettyPort")
#DependsOn("jettyServer")
public Integer jettyPort() throws Exception {
Integer port = jettyServer().getConnectors()[0].getLocalPort();
log.info("Jetty started on port: " + port);
return port;
}
}

Glassfish 4.0 Exception while loading the app, java.lang.IllegalStateException

I am new to web services and glassfish. Here is my code
package ws.mypkg;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
#WebService
#SOAPBinding(style=Style.RPC)
public class TestRPC {
// This seems to cause the problem when a List is returned.
public List<String> testRPC () {
List<String> l = new ArrayList<String>();
l.add("Hello");
return l;
}
// This method work fine
public String testRPC1 () {
return "Testing RPC";
}
}
If I have
#SOAPBinding(style=Style.RPC)
I get the following error when I try to deploy the web service.
cannot Deploy TestGF deploy is failing=Error occurred during deployment: Exception
while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: java.lang.RuntimeException: Servlet web service
endpoint '' failure. Please see server.log for more details.
Server log does not have anything more.
It deploys fine when I comment out #SOAPBinding(style=Style.RPC)
The problem appears to be with the first method. If I exclude the first method, the second method deploys fine. It seems like I am having this problem when I return a list from the method and I have #SOAPBinding(style=Style.RPC)
I am using Glassfish 4.0, jdk 1.7 and Eclipse (bundled in with Spring 3.4)
The problem is that your method return type is an interface and JAXB cannot work with interfaces because it doesn't know which List implementation to use.
To fix it just change the return type of method to ArrayList like this:
public ArrayList<String> testRPC () {
ArrayList<String> l = new ArrayList<String>();
l.add("Hello");
return l;
}
As the error message suggests, more info can be found in the server.log. There should be something like:
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.util.List is an interface, and JAXB can't handle interfaces
this problem is related to the following location:
at java.util.List
This should point you in the right direction if similar errors occur.
See also:
java.util.List is an interface, and JAXB can't handle interfaces

Implementing digital signature on Weblogic ServiceControl Client

Our application is a consumer of a web service that has asked us to implement digital signature (X.509 based) in our request SOAP header. We need to have in the header tags like <ds:SignedInfo>, <wsse:BinarySecurityToken>, <ds:CanonicalizationMethod>. It's actually a lot similar to the xml here.
Now, as a client we are not using clientgen. Nor is the server side willing to make this into a WS-Policy. I searched a lot in the Oracle documentation but it seems to end at the assumption that the server side needs to have this policy enforced to the web service. That can't happen. We can't use client side policy too because the examples I came across at Oracle's website seem to suggest that it only works for client code generated via clientgen while our code uses the ServiceControl.
Just today I came across WSS4J but I am not sure if that is the answer to what I am searching for. It certainly seems plausible but will it work in my scenario (considering that we have Weblogic ServiceController) while all examples for WSS4J seem to use Axis.
I have spent last few days searching on this and I am getting to the point of frustration. Please help!
Thanks,
Ak
I have faced the same problem and finally we are using the Apache CXF library for creating the client and written some interceptors for it. In our case the web service is having authentication header and it is X509 enabled. The below code works for me, I am sharing this with you:-
For generating Web Service Client offline, you can save the xml of the wsdl in your localmachine and then use wsconsume/wsdl2java command for creating the stub.
In the below code you can skip addSoapHeader part if there is no userName and pwd set for the web service
in SOAP Header.
TestClient.java:-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.bind.JAXBException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.AddressingFeature;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.headers.Header;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.ws.addressing.AddressingProperties;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.ws.addressing.VersionTransformer;
import org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.handler.WSHandlerConstants;
import com.icbase.tsamplex509.ArrayOfDetailLineItem;
import com.icbase.tsamplex509.ArrayOfInventoryLineItem;
import com.icbase.tsamplex509.AuthHeader;
import com.icbase.tsamplex509.CompleteInventory;
import com.icbase.tsamplex509.DetailLineItem;
import com.icbase.tsamplex509.InventoryLineItem;
import com.icbase.tsamplex509.OrderAdd;
import com.icbase.tsamplex509.OrderStatus;
import com.icbase.tsamplex509.ResultMessage;
import com.icbase.tsamplex509.Service;
import com.icbase.tsamplex509.ServiceSoap;
import com.st.passport.PassportWebServiceHandler;
import com.st.passport.UserInfo;
import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
public class TestClient
{
private static String proxyUser = "javaMagician";
private static String proxyPassword = "myProxyPws";
private static String proxyHost = "sxf4.dlh.ts.com";
private static String proxyPort = "8080";
private static String wsURL = "http://www.wsdoamin.com/tssamplex509/service.asmx?WSDL";
public static void main(String[] args) throws MalformedURLException, Exception
{
Authenticator.setDefault(new ANSAuthenticationHandler(proxyUser,proxyPassword));
System.getProperties().put("http.proxyHost", proxyHost);
System.getProperties().put("http.proxyPort", proxyPort);
Service service = new Service(new URL(wsURL),new QName("http://www.wsdoamin.com/tssamplex509/", "Service"));
ServiceSoap port = service.getServiceSoap(new AddressingFeature(true,true));
Client client = ClientProxy.getClient(port);
enableWSAddressing(client);
enableWsSecurity(client);
addSOAPHeader(client);
System.out.println("Invoking Web Service ...");
//Calling First Web service
CompleteInventory getProductResponse = port.getproduct("*");
System.out.println("Result :: " + getProductResponse.getResultMessage().getResult().name());
System.out.println("Return Message :: " + getProductResponse.getResultMessage().getMessage());
System.out.println("------------------- Inventory -------------------");
}
private static void enableWSAddressing(Client client) {
AddressingProperties maps = new AddressingPropertiesImpl();
EndpointReferenceType ref = new EndpointReferenceType();
AttributedURIType add = new AttributedURIType();
add.setValue("http://www.wsdoamin.com/tssamplex509/getproduct");
ref.setAddress(add);
maps.setReplyTo(ref);
maps.setFaultTo(ref);
maps.exposeAs(VersionTransformer.Names200408.WSA_NAMESPACE_NAME);
client.getRequestContext().put("javax.xml.ws.addressing.context", maps);
}
private static void enableWsSecurity(Client client) {
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.provider","org.apache.ws.security.components.crypto.Merlin");
properties.put("org.apache.ws.security.crypto.merlin.keystore.type","jks");
properties.put("org.apache.ws.security.crypto.merlin.keystore.password","changeit");
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias","ts_p&s_ws");
properties.put("org.apache.ws.security.crypto.merlin.file", "cert/TS_P&S_WS.jks");
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.USER, "ts_p&s_ws");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,ANSAuthenticationHandler.class.getName());
outProps.put("cryptoProperties", properties);
outProps.put(WSHandlerConstants.SIG_PROP_REF_ID,"cryptoProperties");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
client.getEndpoint().getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
client.getEndpoint().getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor());
client.getEndpoint().getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor());
}
private static void addSOAPHeader(Client client) throws JAXBException {
List<Header> headers = new ArrayList<Header>();
AuthHeader authHeader = new AuthHeader();
authHeader.setUsername("ts");
authHeader.setPassword("46u43242bw3670");
SoapHeader tokenHeader = new SoapHeader(new QName("http://www.wsdoamin.com/tssamplex509", "AuthHeader"), authHeader,new JAXBDataBinding(AuthHeader.class));
headers.add(tokenHeader);
client.getRequestContext().put(Header.HEADER_LIST, headers);
}
}
ANSAuthenticationHandler.java
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ANSAuthenticationHandler extends Authenticator implements CallbackHandler {
private String proxyUser;
private String proxyPassword;
public ANSAuthenticationHandler() {
super();
}
public ANSAuthenticationHandler(String proxyUser, String proxyPassword) {
super();
this.proxyUser = proxyUser;
this.proxyPassword = proxyPassword;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
System.err.println("CallbackHandler providing password for :: "+pc.getIdentifier());
if ("ts_p&s_ws".equals(pc.getIdentifier())) {
pc.setPassword("changeit");
}
}
public PasswordAuthentication getPasswordAuthentication()
{
System.err.println("Feeding username and password for ["+getRequestingPrompt()+"] to ["+getRequestingHost()+":"+getRequestingPort()+"] for ["+getRequestingScheme()+"] scheme");
return (new PasswordAuthentication(proxyUser, proxyPassword.toCharArray()));
}
}

Disable auto generated JAX-WS Status Page

When I deploy and run my web service developed with JAX-WS I can see a summary page with some info on it, something like in this picture:
http://www.mkyong.com/webservices/jax-ws/deploy-jax-ws-web-services-on-tomcat/
For the final implementation we would like to remove this page so that a custom or a blank page is returned while still having access to the web service endpoint.
We are currently running on Tomcat.
There is a field on the WSServlet class that might do what you are looking for: JAXWS_RI_PROPERTY_PUBLISH_STATUS_PAGE (it's value is com.sun.xml.ws.server.http.publishStatusPage).
Looking at the source code from a JAX-WS download it seems that you need to set it as a context parameter in your web.xml file:
<web-app>
<context-param>
<param-name>com.sun.xml.ws.server.http.publishStatusPage</param-name>
<param-value>false</param-value>
</context-param>
...
Seems that HttpAdapter had something similar on it but was taken from an environment variable:
setPublishStatus(
System.getProperty(HttpAdapter.class.getName() + ".publishStatusPage")
.equals("true"));
The code on HttpAdapter is marked deprecated in the javadoc so the context parameter seems the way to go.
I have been trying to solve this for two days, Glassfish 3.1.2.
The only solution was to have
-Dcom.sun.xml.ws.transport.http.HttpAdapter.publishStatusPage=false
I know its old, but wantd to maintain the knowledge. Hope this helps any one with this issue.
I have completed the same task for WebLogic recently.
It was requested to hide/show a status page of a public web service depending on a target environment i.e. hide for production, show for dev.
Nothing of the previous answers worked for me.
The success solution is based on implementation of javax.servlet.Filter.
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.HttpMethod;
#WebFilter(urlPatterns = { "/WeblogicWebService" })
public class FilterStatusSoapPage implements Filter {
#Value("${soap.status.page.disabled}")
private boolean flagDisablePublishStatusPage;
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
String queryString = httpReq.getQueryString();
if(flagDisablePublishStatusPage)
if(queryString == null || queryString.trim().isEmpty())
if(HttpMethod.GET.matches(httpReq.getMethod())) {
httpRes.setStatus(HttpServletResponse.SC_OK);
httpRes.getWriter().write("Access to status page of Web
Service is not allowed");
httpRes.getWriter().flush();
httpRes.getWriter().close();
return;
}
} catch (Exception e) {
System.err.println("Error on FilterStatusSoapPage filter");
chain.doFilter(request, response);
return;
}
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {}
public void destroy() {}
}

SOAP Debug message not getting printed

I set -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true in my client VM arguments. I am using JAX-WS client. But inspite of that SOAP Message is not getting printed in the console. Any reason?
This is my client code.
package com.helloworld.client;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import com.helloworld.ws.HelloWorld;
public class HelloWorldClient{
public static void main(String[] args) throws Exception {
URL url = new URL("http://localhost:9999/ws/hello?wsdl");
//1st argument service URI, refer to wsdl document above
//2nd argument is service name, refer to wsdl document above
QName qname = new QName("http://ws.helloworld.com/", "HelloWorldImplService");
Service service = Service.create(url, qname);
HelloWorld hello = service.getPort(HelloWorld.class);
System.out.println(hello.getHelloWorldAsString("Test String"));
}
}
My server is I published using Endpoint.publish and is running locally.
on Server
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
You can also use #HandlerChain(file = "....") annotation
More about Jax-WS Handlers here and here
This is the correct VM argument -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true. Are you using any IDEA?