How to solve ServiceConstructionException: Could not find definition for service? - web-services

I have a simple application with an web service created with Apache CXF. This application works when I run the server and the client (as Java applications). When I try to access the application /services URL which is mapped in web.xml, Tomcat gives me 404 error. When I run the project I receive:
org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for service {http://sendmessage/}SendMessage
If anyone has any hints related to this error I would be glad to hear them. (I searched google and couldn't find something relevant to my situation)
Thank you!

I had same error, mine was related to namespace which were different in wsdl and webservice. So I changed them to the same.
WSDL:
<wsdl:definitions name=""
targetNamespace="http://www.example.org/yourservice/"
Webservice class:
#WebService(targetNamespace = "http://www.example.org/yourservice/",
.........

Even I had a similar issue.
Fixed it by updating the jaxws:endpoint.
I added the serviceName (mapping to the name present in the WSDL file) with the name space as defined in the "targetNamespace" defined in the wsdl:definitions tag.
<jaxws:endpoint id=".." implementor="..." serviceName="s:SERVICE_NAME_IN_WSDL"
xmlns:s="TARGET_NAME_SPACE_WSDL_DEFINTIONS"></jaxws:endpoint>
edited(06Jul)
Also, I have today that, with Apache CXF 3.0.5 version this issue is not coming;
But with Apache CXF 3.1 version, this is coming.

ServiceConstructionException can occur at various stages when cxf compares the provided service, port and binding name with the wsdl it has already parsed. In this case ( and in most cases) it looks to be namespace issue.
{http://sendmessage/}SendMessage is either not present in parsed wsdl or the service name does not match with the QName present in the WSDL. There are other cases as well where binding or port does not match, one might receive the same exception. Following is a code snippit from org.apache.cxf.wsdl11.WSDLServiceFactory.create() method where it all happens.
If things are not clear why exactly it is happening your best bet is to debug this piece of code and see where it is failing and what is there in parsed wdsl definition (com.ibm.wsdl.DefinitionImpl in wsdl4j.jar).
javax.wsdl.Service wsdlService = definition.getService(serviceName);
if (wsdlService == null) {
if ((!PartialWSDLProcessor.isServiceExisted(definition, serviceName))
&& (!PartialWSDLProcessor.isBindingExisted(definition, serviceName))
&& (PartialWSDLProcessor.isPortTypeExisted(definition, serviceName))) {
try {
Map<QName, PortType> portTypes = CastUtils.cast(definition.getPortTypes());
String existPortName = null;
PortType portType = null;
for (QName existPortQName : portTypes.keySet()) {
existPortName = existPortQName.getLocalPart();
if (serviceName.getLocalPart().contains(existPortName)) {
portType = portTypes.get(existPortQName);
break;
}
}
WSDLFactory factory = WSDLFactory.newInstance();
ExtensionRegistry extReg = factory.newPopulatedExtensionRegistry();
Binding binding = PartialWSDLProcessor.doAppendBinding(definition,
existPortName, portType, extReg);
definition.addBinding(binding);
wsdlService = PartialWSDLProcessor.doAppendService(definition,
existPortName, extReg, binding);
definition.addService(wsdlService);
} catch (Exception e) {
throw new ServiceConstructionException(new Message("NO_SUCH_SERVICE_EXC", LOG, serviceName));
}
} else {
throw new ServiceConstructionException(new Message("NO_SUCH_SERVICE_EXC", LOG, serviceName));
}
PS: I know this issue was opened back in 2011 but recently I faced the same issue and was able to resolve it. I hope it help others who are facing this issue.

Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for port {http://localhost:9990/project/wsdl/targetName}targetNameSoap12.
at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:179)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:428)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:548)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:265)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:215)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:102)
at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:159)
at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:211)
at org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:456)
at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:334)
... 13 more
Fixed problem, define at annotation #WebService(targetNameSpace = "targetNameSoap12") in your web service interface and in the contract WSDL.
For exemplo:
...
<wsdl:service name='targetName'>
<wsdl:port binding='tns:targetNameSoap12' name='targetNameSoap12'>
...

Related

Use wsse security header in soap message (Visual Studio 2015, .Net Framework 4.5)

I would like to consume a Soap Service provided by DHL. You can find the wsdl here: https://wsbexpress.dhl.com/sndpt/expressRateBook?WSDL
Therefore I created a new ClassLibrary in Visual Studio 2015 targeting .net framework 4.5.
Then I added a Web Reference to the created project by providing the wsdl address. I generated a proxy file with all types and ports in it but my first problem is, that the generated Service extends from System.Web.Services.Protocols.SoapHttpClientProtocol. As I read in recent posts it is not possible to get the wsse header to that proxy. Some posts advise to add wse but it seems wse is not supported by newer Visual Studio versions.
I tried to generate my proxy by svcutil. After that I added the generated .cs file to the project and copied the content of the generated config file to app.config. (of cause I removed the web reference)
Now the Service class extends System.ServiceModel.ClientBase. (I thought the generator in VS uses svctool internally. If microsoft want people to use wcf why does the generator generate non-wcf proxy files.
I also created a nunit testproject which should test my service, but If I use the version with the svcutil generated version I get an error. I try to translate it to english as the error is displayed in german:
Could not find a default endpoint element which points to the service contract. As I figured out this is because the proxy is in its own class library and therefor doesn't really have an app.config. But my test project is a class library too.
What would be the actual way to consume a web service which needs ws security Username/Password auth these days?
You can add the Web Reference in compatibility mode (I am guessing you are doing so). If you are not adding the reference in compatibility mode, do the following:
Right click on references Add Service Reference-> Advanced -> Add Web Reference (Below the compatibility section), type the URL of the WS and add the reference.
The WSE2.0 extensions are available as a Nuget Package at:
https://www.nuget.org/packages/Microsoft.Web.Services2/
Install the nuget package on the package manager console running the following nugget command:
Install-Package Microsoft.Web.Services2
After you installed the nuget package, you need to make sure your project is referencing the following DLL's:
System.Web
System.Web.Services
Microsoft.Web.Services2 (This will be added after you install the nuget package)
In order to use the WSE2.0 extensions, you need to actually modify the Proxy class that was created when you added the WebReference to inherit from "Microsoft.Web.Services2.WebServicesClientProtocol" instead of "System.Web.Services.Protocols.SoapHttpClientProtocol". Be aware that if you update the WebReference, the Proxy class will inherit againfrom SoapHttpClientProtocol.
Add the following using clauses to the code consuming the Proxy class:
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
After you make this changes, you code should look something like this:
var token = new UsernameToken("theUser", "thePassword", PasswordOption.SendHashed);
var serviceProxy = new ExpressRateBook.gblExpressRateBook();
SoapContext requestContext = serviceProxy.RequestSoapContext;
requestContext.Security.Timestamp.TtlInSeconds = 60;
requestContext.Security.Tokens.Add(token);
//The rest of the logic goes here...
I added the screenshot down below for your reference:
NOTE: I was unable to test the code since I am unfamiliar with the actual methods that you need to consume, the code displayed is just an example of what I saw in the proxy class, update it according to your needs. It should work fine if you follow the steps described before. Check the following link for more detailed instructions:
https://msdn.microsoft.com/en-us/library/ms819938.aspx
You can configure you Service Reference to add the Security Header as AW Rowse describes at http://cxdeveloper.com/article/implementing-ws-security-digest-password-nonce-net-40-wcf:
private void Configure()
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; };
defaultBinding = new BasicHttpBinding
{
Security =
{
Mode = BasicHttpSecurityMode.Transport,
Transport =
{
ClientCredentialType = HttpClientCredentialType.Digest
}
}
};
defaultToken = new UsernameToken(UserName, Password, PasswordOption.SendHashed);
defaultSecurityHeader = MessageHeader.CreateHeader(
"Security",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
defaultToken.GetXml(new XmlDocument())
);
}
And create you client/proxy like this:
public consulta_informacao_respttClient CriaConsultaClinicaClient()
{
var client = new consulta_informacao_respttClient(defaultBinding, new EndpointAddress("https://resqa.homologacao.unimed.coop.br/chs-integration-external-services-ptu-clinical/proxy-services/execute-query/execute-query-proxy-service"));
client.ClientCredentials.UserName.UserName = UserName;
client.ClientCredentials.UserName.Password = Password;
var scope = new OperationContextScope(client.InnerChannel);
OperationContext.Current.OutgoingMessageHeaders.Add(defaultSecurityHeader);
return client;
}
The properties you will need to create in your class are:
private BasicHttpBinding defaultBinding;
private UsernameToken defaultToken;
private MessageHeader defaultSecurityHeader;
You won't need to configure anything in app/web.config.

Apply HTTP basic authentication to jax ws (HttpSpiContextHandler) in embedded Jetty

There are some similar questions for earlier versions of Jetty (pre 9) but none that address this specific problem :
Server server = new Server();
System.setProperty("com.sun.net.httpserver.HttpServerProvider",
JettyHttpServerProvider.class.getName());
JettyHttpServer jettyServer = new JettyHttpServer(server, true);
Endpoint endpoint = Endpoint.create(new SOAPService()); // this class to handle all ws requests
endpoint.publish(jettyServer.createContext("/service")); // access by path
server.start()
Simplified code example above to show the only way that I have found to bridge between Jetty and incoming soap requests to my jax-ws service. All settings are in code with no web.xml, this is part of a larger solution that has multiple contexts and connections for different purposes (servlets etc..)
I have tried to add a handler class to the jettyServer.createContext("/service",new handler()) to see if I can perform a header extraction to simulate basic auth but it never gets executed.
My problem is that i cannot find a way to specify, by code against the Jetty server, to use basic authentication. Using the setSecurityHandler method of a ServletContextHandler is easy and works great for other contexts, i just can't figure out how to use this concept for the jax-ws service.
Any help would be much appreciated.
p.s. SSL is already implemented, I just need to add http basic auth.
For anyone else that may of come across the same problem here is the answer that i stumbled on eventually.
final HttpContext httpContext = jettyServer.createContext("/service");
com.sun.net.httpserver.BasicAuthenticator a = new com.sun.net.httpserver.BasicAuthenticator("") {
public boolean checkCredentials (String username, String pw)
{
return username.equals("username") && pw.equals("password");
}
};
httpContext.setAuthenticator(a);
endpoint.publish(httpContext);//access by path
You can expand the checkCredentials for something a bit more sophisticated of course, but this shows the basic working method.

Embed jetty in java app and export as jar

I'm making a java application which embeds a Jetty web server, which in turn serves content developed with Google Web Toolkit. It's all working fine when run in Eclipse, but when I export it as a jar file all I get is a Jetty error message saying "File not found".
The Jetty server is launched like this:
WebAppContext handler = new WebAppContext();
handler.setResourceBase("./war");
handler.setDescriptor("./war/WEB-INF/web.xml");
handler.setContextPath("/");
handler.setParentLoaderPriority(true);
server.setHandler(handler);
try {
server.start();
server.join();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I suspect that the problem is the relative paths used in handler.setResourceBase() and handler.setDescriptor(). I've googled and tested lots of solutions to this but so far to no avail. Particularly I've tried using something like getClass().getResource("./war").toExternalForm() but this just throws Null exceptions.
I also tried:
ProtectionDomain protectionDomain = Start.class.getProtectionDomain();
URL location = protectionDomain.getCodeSource().getLocation();
but that only results in a Jetty serving a directory listing of the java classes.
Is there any way to do this?
Copy all files of the compiled GWT application into one of your Java packages. For instance:
my.webapp.resources
html/MyPage.html
gwtmodule/gwtmodule.nocache.js
...
(html, gwtmodule will become Java packages as well).
Configure the embedded Jetty instance to serve these files.
final String webDir = this.getClass().
getClassLoader().getResource("my/webapp/resources").toExternalForm();
final Context root = new Context(server, "/", Context.SESSIONS);
root.setContextPath("/");
root.setResourceBase(webDir);
root.addServlet(MyGwtService.class, "/servlets/v01/gwtservice");
This approach works for me both when the application is run from eclipse as well as when it is deployed.
I've posted a detailed description on how to do this here:
http://h30499.www3.hp.com/t5/HP-Software-Developers-Blog/Embedding-Jetty-in-a-Java-Main-Application/ba-p/6107503
It looks like ClassLoader.getResource does not understand an empty string or . or / as an argument. In my jar file I had to move all stuf to WEB-INF. So the code looks like
`contextHandler.setResourceBase(EmbeddedJetty.class.getClassLoader().getResource("WEB-INF").toExternalForm());`
so the context looks like this then:
ContextHandler:744 - Started o.e.j.w.WebAppContext#48b3806{/,jar:file:/Users/xxx/projects/dropbox/ui/target/ui-1.0-SNAPSHOT.jar!/WEB-INF,AVAILABLE}

JAX-WS web service with Source return type on Websphere

I am migrating an old JAX-WS 2.1 web service from JBoss 4 to Websphere 7. Most of the #WebMethod components all look like this:
#WebMethod
public Source someMethod(){
Source source = null;
try{
source = ServiceActions.someMethodWorker();
}
catch( Throwable throwable ){
source = ServiceActions.handleThrowable("Error occured in method someMethod", throwable );
}
return source;
}
ServiceActions.someMethodWorker() usually goes off and fetches that data populates a JAXB structure, marshalls into XML and returns a StreamSource of the XML like this:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
JAXBContext jc = JAXBContext.newInstance();
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(someJaxBObjectHierarchy, byteArrayOutputStream);
return new StreamSource(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
This web service runs just fine on JBoss 4 (with the Jax-WS and JaxB libraries) and GlassFish 3.1, but Websphere 7 keeps giving me the following error any time I use a client against the web service:
javax.xml.ws.soap.SOAPFaultException: javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class javax.xml.transform.stream.StreamSource nor any of its super class is known to this context.]
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
At first look this seems to be the JAXB type binding problem; however, I've added #XmlSeeAlso(StreamSource.class) everywhere, and I still get the error.
Would someone know why this is failing on WebSphere 7?
Thanks!
Edit/Solution: The solution is to use byte[] return type instead of Source
GlassFish and JBoss were doing something extra compared to the JAX-WS specification which led me to believe that Source return type was OK.
Instead of my methods returning new StreamSource(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) they now just return byteArrayOutputStream.toByteArray()
javax.xml.transform.Source is not a valid return type for a normal JAX-WS service endpoint interface (SEI). If you want to do that (and be compliant with JAX-WS) you need to use a service that is implemented as a javax.xml.ws.Provider (see the corresponding docs). If JBoss or GlassFish support Source as a parameter or return type in a normal SEI, then that's a proprietary extension.

Getting started with embedded Jetty

I just got started with embedded jetty. I'm stuck at some error messages. It's simple and straightforward few lines code, which I found online and wanted to test out.
import org.jaxen.Context;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHolder;
public class Main {
public static void main(String[] args) throws Exception {
ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
sh.setInitParameter("com.sun.jersey.config.property.packages", "jerseyplusjetty");
Server server = new Server(80);
ServletContextHandler sch = new ServletContextHandler(server, "/");
sch.addServlet(sh, "/*");
server.start();
server.join();
}
}
I have all jetty jars in java build path. But I kept getting errors: The constructor ServletHolder(Class) is undefined, The constructor Server(int) is undefined, ServletContextHandler cannot be resolved to a type.
If I remove the parameter inside ServletHolder and Server, it stops complaining. e.g. if I have: ServletHolder sh = new ServletHolder(); Server server = new Server();
But that's not right. I read Jetty docs and ServletHolder class can take parameters. Am I missing something here?
Just FYI on embedded Jetty in general... I have created a github project that I humbly submit may cover most of the embedded jetty issues that keep cropping up.
I've got examples for AbstractHandlers, Servlets, Jersey Servlets, static files, webapps and what not. Still working on RoR and Sinatra, but will get there.
See https://github.com/ZenGirl/EmbeddedJettyRepository for details.
Anyone want to contribute, just ask.
The version of ServletHolder I have takes a String or a servlet in the constructor. So instead of doing
new ServletHolder(ServletContainer.class) you should do new ServletHolder(ServletContainer.class.getCanonicalName()) or new ServletHolder(new ServletContainer()).
ServletContainer is a strange name for a servlet, make sure it is actually a servlet.
Also, be aware that there are number of different versions of Jetty (you're using an old one because in the new one all the classes are in org.eclipse.jetty package), and it's easy to pick up example code that refers to a different version to the one you've got. I would get jetty 7.2.2 from maven and use the example code here.