Web Service exception - link without "?wsdl", HTTP GET PATH_INFO - java

I have simple web service :
I have the same problem. when I don't append "?wsdl" I have soap faylt. how can I avoid this exception?
#WebService
#SOAPBinding(style = Style.RPC)
public interface TimeServer {
#WebMethod
#WebResult(partName = "time_response")
String getTimeAsString();
#WebMethod
#WebResult(partName = "time_response")
long getTimeAsElapsed();
}
and impl:
#WebService(endpointInterface = "x.y.z.TimeServer")
public class TimeServiceImpl implements TimeServer {
public TimeServiceImpl() {}
#Override
public String getTimeAsString() {return new Date().toString();}
#Override
public long getTimeAsElapsed() {return new Date().getTime();}
}
I run this web service in Jboss As 7.0.1.
Everything works well!
When I open link localhost:8080/project/time?wsdl
everything works well - I have wsdl.
but when I don't append "?wsdl" I have exception.
14:26:58,192 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-localhost-127.0.0.1-8080-1) Interceptor for {http://x.z.y/}HelloWorld has thrown exception, unwinding now: org.apache.cxf.interceptor.Fault: No such operation: null (HTTP GET PATH_INFO: /project/timenull)
at org.apache.cxf.interceptor.URIMappingInterceptor.handleMessage(URIMappingInterceptor.java:88)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
and I have this response from server:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>
No such operation: null (HTTP GET PATH_INFO: /soap-service/timenull)
</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
how can I avoid this exception?
It will be better , if client will see another message, instead of this error response? how can I send another XML when client opens link without "?wsdl"?
thnaks

Webservices won't support HTTP GET. If you enter the service url its directly making a HTTP GET. Thats the reason it responds with the error No such operation
Instead you need to make a SOAP POST to get response from webservice. Write a webservice client for this. You can refer this link for creating webservice clients

#grep
I see this post as bit old, but still will try to answer if anyone else with similar problem is able to. Well, I had the same issue and wondered what were the reasons behind those. here are the two steps that i tried and fixed up the issue. make sure you are able to access the wsdl in browser.
Close the SOAPUI, delete the soapui_workspace.xml created in user folder under C:/users.
Restart the Soap_ui and open up preferences>Proxy setting.
Change from automatic to None.
Create new project.
This did solved my issue and got the response from webservice in SOAPUI.
Secondly, in this case, make sure you have deployed the webservice correctly as mentioned by #Dinal.

Related

Unable to set SOAP Header while calling Web Service through Camel using dataFormat as POJO

I am using Camel in our project and requesting WebServices, the dataFormat is POJO. I was able to request when my SOAP message did not contain SOAP headers, but when it had Headers, I was unable to set those. I looked at the documentation but was not able to understand and have several questions.
I want to create a message like the below:
<soapenv:Envelope`enter code here`
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<platformMsgs:documentInfo
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformMsgs:nsId>WEBSERVICES_3479023</platformMsgs:nsId>
</platformMsgs:documentInfo>
</soapenv:Header>
<soapenv:Body>
<addListResponse
xmlns="">
<platformMsgs:writeResponseList
xmlns:platformMsgs="urn:messages_2015_1.platform.webservices.netsuite.com">
<platformCore:status isSuccess="true"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com"/>
<platformMsgs:writeResponse>
<platformCore:status isSuccess="false"
xmlns:platformCore="urn:core_2015_1.platform.webservices.netsuite.com">
<platformCore:statusDetail type="ERROR">
<platformCore:code>DUP_ENTITY</platformCore:code>
<platformCore:message>This entity already exists.</platformCore:message>
</platformCore:statusDetail>
</platformCore:status>
</platformMsgs:writeResponse>
</platformMsgs:writeResponseList>
</addListResponse>`enter code here`
</soapenv:Body>
</soapenv:Envelope>
I will be able to send the message if there was only Body, but can someone give me a code snippet for including the header section? The dataFormat is POJO.
When using CXF endpoint with dataFormat as POJO, body in Camel Exchange object is an object of org.apache.cxf.message.MessageContentsList. It is an extension of java.util.ArrayList<Object> and it contains parts of SOAP Message in order as defined in WSDL and corresponding method in WebService class.
Element 0 there is a Body.
So, one way to do that with Java is to create a Processor class implementing org.apache.camel.Processor interface and in its process method set your SOAP header. Something like:
#Override
public void process(Exchange camelExchange) throws Exception {
MessageContentsList messageBody = (MessageContentsList) camelExchange.getIn().getBody();
DocumentInfo docInfoHeader = new DocumentInfo();
... set docInfoHeader properties ...
messageBody.add(docInfoHeader);
}
(sample is not tested. It is just an idea, how to handle that...)
Other answer on similar question you can find here: Setting Custom Soap Header-To Pojo Message In Camel Cxf
It describes how to use Camel Exchange headers as SOAP Headers.
I'm not sure for 100% which way will work for you and which one is better...
I guess, it depends on WSDL you use.
UPD: second choice is to use pure CXF solution by using CxfMessageSoapHeaderOutInterceptor custom implementation.
It may look like:
public class MyCxfInterceptor extends CxfMessageSoapHeaderOutInterceptor {
#Override
public void handleMessage( org.apache.cxf.binding.soap.SoapMessage message) {
org.apache.cxf.binding.soap.SoapHeader myCustomHeader = new org.apache.cxf.binding.soap.SoapHeader(new QName(
{custom name space}, {custom local name}), {Custom content object}));
myCustomHeader.setMustUnderstand(true);
message.getHeaders().add(myCustomHeader);
}
and set Interceptor in Camel Cxf Endpoint as :
<cxfEndpoint ...>
<outInterceptors>
<spring:bean class="MyCxfInterceptor"/>
</outInterceptors>
...
Well suppose I request the Web Service and it failed, a Fault message is generated. Will I get the Fault object at position 0 of MessageContentsList then too? Or will I get only the response object at position 0?

Create custom exceptions in Axis2

I'm using Axis2 1.5.2 and Eclipse. I'm using Eclipse to generate the WSDL and client code from generated WSDL.
I created a custom exception that my service can throw. Everything looks ok when creating the webservice. The webservice starts successfully and I can view the generated WSDL by pointing my web browser.
But when I tell Eclipse to generate the Client code using the generated WSDL I get this error from Eclipse:
Error in generating Java from WSDL: java.io.IOException: ERROR: Missing <soap:fault> element inFault "InsertUserException" in operation "InsertUserException", in binding insertUser
java.io.IOException: ERROR: Missing <soap:fault> element inFault "InsertUserException" in operation "InsertUserException", in binding insertUser
at org.apache.axis.wsdl.symbolTable.SymbolTable.faultsFromSOAPFault(SymbolTable.java:2858)
My custom exception is "InsertUserException":
public class InsertUserException extends Exception{
private String errorCode;
public InsertUserException(String errorCode){.....}
public String getErrorCode(){...}
public void setErrorCode(String errorCode){...}
}
My service action that clients can call is "insertUser":
public void insertUser() throws InsertUserException{
.....
}
Any help is appreciated.
Axis2 doesn't know how to send Exceptions over the wire unless they are AxisFaults.
Here's a link to an article on how to use AxisFault with custom exception information.
http://wso2.org/library/171

Null content-type when migrating from Jersey to RESTEasy.

So I wrote a sample REST resource that works like a charm in Jersey/Tomcat, but when I take it to RestEASY/Tomcat it blows. I mean really? what happened to working out of the box. Anyway a little frustrated. I get this error when trying to access the resource(http://localhost:7070/mg/mytest)
"content-type was null and expecting to extract a body"
7842 [http-7070-2] ERROR com.loyalty.mg.rest.exception.MGExceptionMapper - Error caught in the exception mapper -
org.jboss.resteasy.spi.BadRequestException: content-type was null and expecting to extract a body
at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:131)
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:98)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:121)
at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:247)
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:212)
at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:202)
#Path("/mytest")
public class TestResource {
#GET
public Response getData()
I guess the question also is - is RestEASY any better than Jersey, this is just the start and I am getting errors. Should I just stick to Jersey?
Also already tried this as well :)
<context-param>
<param-name>resteasy.media.type.mappings</param-name>
<param-value>json : application/json, xml : application/xml</param-value>
</context-param>
The code that throws that exception looks like this:
final MediaType mediaType = request.getHttpHeaders().getMediaType();
if (mediaType == null) {
throw new BadRequestException(
"content-type was null and expecting to extract a body");
}
The problem seems to be that RestEASY cannot figure out a content type from the headers of the request that it received. This suggests that either that the content type in the request is bogus, or that there is a problem with the way that you have configured RestEASY.
I guess the question also is - is RestEASY any better than Jersey, this is just the start and I am getting errors. Should I just stick to Jersey?
I cannot answer that. However, I think you are being too quick to blame RestEASY for something that could be your code's fault.
A classic cause of this, is if you have code like this:
#GET
#Path("/foo/{bar}")
#Produces(MediaType.TEXT_HTML)
public Response foo(#PathParam("bar") String bar) {
...and you forget to annotate the bar argument with #PathParam. Then RestEasy thinks it should be reading bar from the body of the request, instead of from the URL path, and will chuck this exception.
That doesn't seem to be what's happening in your case, but I got the same exception, and this was the cause.
RestEASY vs Jersey is hard to say:
http://www.infoq.com/news/2008/10/jaxrs-comparison
Regarding your error, you can control the content type via annotations, what happens if you place #Produces annotation, for example:
#Produces("application/json")
#GET
public Response getData() {
...
}
Well I know this requested is dated, and so much on the internet old..in a year of two everything usually changes and works better. So RestEasy should not get a bad rap in comparison to other non-propertary RESTLET frameworks.
Actually I think JBoss RestEasy has the lightest footprint, it's not bloated with unnecessary *.jars, flexible, fully certified JAX-RS implementation, complete and its ease of use is beyond comparison.
Some eluded, that a GET request should not expect a Content_Type on the request, (And I agree), but with a every GET request one must indicate what you intend on sending back to the requestor? Right! (will it be JSON, XML, plain text, XML and a sheetsheet, multi-part, etc). Well RestEasy, JBoss's framework addresses this with annotation as shown below, and configurable per URL REST request. Therefore, therein is your answer
#GET
#Path("/echo/{message}")
#Produces("text/plain")
public String echo(#PathParam("message")String message){
return message;
}
#GET
#Path("/employees")
#Produces("application/xml")
#Stylesheet(type="text/css", href="${basepath}foo.xsl")
public List<Employee> listEmployees(){
return new ArrayList<Employee>(employees.values());
}
#GET
#Path("/employee/{employeeid}")
#Produces("application/xml")
public Employee getEmployee(#PathParam("employeeid")String employeeId){
return employees.get(employeeId);
}
#GET
#Path("/json/employees/")
**#Produces("application/json")**
public List<Employee> listEmployeesJSON(){
return new ArrayList<Employee>(employees.values());
}
a GET request must not have a body, and an application must not expet a Content-Type header.
If this is a bug of RestEASY, it makes one wonder how many people really are using the software.
EDIT
RFC2616 $4.3
A message-body MUST NOT be included in
a request if the specification of the
request method (section 5.1.1) does
not allow sending an entity-body in
requests.
A server SHOULD read and forward a
message-body on any request; if the
request method does not include
defined semantics for an entity-body,
then the message-body SHOULD be
ignored when handling the request.
The GET method does not "does not allow sending an entity-body in request" therefore a GET request COULD have a body. But GET "does not include defined semantics for an entity-body" therefore the body should be ignored anyway.
In any case, RestEASY should not have required the presence of Content-Type in a GET request.

Why are error pages ignored in RESTEasy web service running on Tomcat?

I'm developing a REST-ful web service using RESTEasy deployed on Tomcat. I've configured an error page which takes the exception's message and generates an XML based on it when any exception occurs during the request.
This works fine for any application generated exceptions. However, if client sends an invalid XML which cannot be unmarshalled correctly, an javax.xml.bind.UnmarshalException is thrown and Tomcat's default error page is used instead of mine.
I have configured my error page to the error-code 500 in web.xml.
Is using error pages the correct way to handle errors when using RESTEasy or is there an alternative way?
The best way is to use an ExceptionMapper. You create a class UnmarshalExceptionMapper that implements ExceptionMapper. You annotate this with "#Provider" and in your Application constructor you do "classes.add(UnmarshalExceptionMapper.class)" or "singletons.add(new UnmarshalExceptionMapper())".
Your exception mapper will look something like this:
#provider
public class UnmarshalExceptionMapper
implements ExceptionMapper<UnmarshalException> {
public Response toResponse(UnmarshalException exception) {
ResponseBuilder rb =
Response.status(
Response.Status.BAD_REQUEST) // Most appropriate HTTP status code
.entity(your xml goes here)
.type("application/xml");
return rb.build();
}
}
Note that you must set the type to "application/xml" because currently content negotiation is NOT done for exception mappers. To do your own content negotiation, get the HttpHeaders from the request, find the "accept" header, and set the type accordingly.

How to get jersey logs at server?

I am using jersey for a REST WS. How do I enable jersey logs at server side?
Long story:
I get a clientside exception - but I don't see anything in tomcat logs [It doesn't even reach my method]. Since the stack trace is saying "toReturnValue" it did get something from server. But I don't know what the server said.
Exception in thread "main" java.lang.IllegalArgumentException: source parameter must not be null
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:98)
at com.sun.xml.internal.ws.message.AbstractMessageImpl.readPayloadAsJAXB(AbstractMessageImpl.java:100)
**at com.sun.xml.internal.ws.client.dispatch.JAXBDispatch.toReturnValue(JAXBDispatch.java:74)**
at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:191)
at com.sun.xml.internal.ws.client.dispatch.DispatchImpl.invoke(DispatchImpl.java:195)
If you want to turn on logging on the server side, you need to register the LoggingFilter Jersey filter (on the container side).
This filter will log request/response headers and entities.
Here's what you need to add to your ResourceConfig class:
#ApplicationPath("/")
public class MyApplication extends ResourceConfig {
public MyApplication() {
// Resources.
packages(MyResource.class.getPackage().getName());
register(LoggingFilter.class);
}
}
Note that the same filter also works on the client side.
Client client = Client.create();
client.addFilter(new LoggingFilter());
Jersey 2 has deprecated LoggingFilter and you now need to use LoggingFeature. In order to use it with a client you can use the following snipette:
this.client = ClientBuilder
.newBuilder()
.property(LoggingFeature.LOGGING_FEATURE_VERBOSITY_CLIENT, LoggingFeature.Verbosity.PAYLOAD_ANY)
.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_CLIENT, "WARNING")
.build();
and on the server side:
ResourceConfig config = new ResourceConfig(HelloWorldResource.class);
config.register(LoggingFeature.class);
Jersey 2.0 uses org.glassfish.jersey.filter.LoggingFilter
You can connect it with help of web.xml
<!-- Register my custom provider (not needed if it's in my.package) AND LoggingFilter. -->
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter</param-value>
</init-param>
More explanations can be found here
upd:
After version 2.23 LoggingFilter is deprecated and LoggingFeature should be used.
More info can be found in official documentation
For Jersey 1.2 add the following entry into web.xml inside the servlet tag:
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
</init-param>
Could you show us your client code and tell us about the request as well?
This exception seems to point at the JAXB unmarshalling step. Apparently you received some XML from your REST API, but you don't get what you're waiting for.
Maybe the XSD you're using for marshalling/unmarshalling is outdated or just plain wrong.
Maybe you're trying to get the wrong entity from the response.
Try these steps and give us some more details about your problem:
Get the XML from the response
Using a REST client like Client REST simple (a chrome extension), or your code:
Builder builder = webResource.path("/yourapi/").accept("application/xml");
// get the client response
ClientResponse response = builder.get(ClientResponse.class);
// log the HTTP Status
logger.log("HTTP Status: " + response.getStatus());
// bypass the jaxb step and get the full response
// MyResource myResource = response.getEntity(MyResource.class);
String myResource = response.getEntity(String.class);
logger.log(myResource);
Validate this XML with the XSD you're using
This test should fail (if I'm right).

Categories

Resources