#WebParam is always null in jetty serving soap - java

I have a java app exposing an SOAP API through Jetty. I can successfully access my WSDL and forge a request, but the webparam sent is always null. I don't know how to debug this problem.
Here i have a few snippets of the functions involved in the request.
I'll edit if you need more information:
#WebMethod(
operationName = "findEvent"
)
public ServiceEventDto findEvent(
#WebParam(name = "eventId") Long eventId) throws InstanceNotFoundException {
Event event
= EventServiceFactory.getService().findEvent(eventId);
return EventToEventDtoConversor.toEventDto(event);
}
This is the request:
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:eve="http://ws.udc.es/event">
<x:Header/>
<x:Body>
<eve:findEvent>
<eve:eventId>0</eve:eventId>
</eve:findEvent>
</x:Body>
Thank you in advance.

I believe the problem is that your SOAP input is using the eve namespace prefix for the eventId input element.
Try this:
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/" xmlns:eve="http://ws.udc.es/event">
<x:Header/>
<x:Body>
<eve:findEvent>
<eventId>0</eventId>
</eve:findEvent>
</x:Body>
I was able to recreate using the following service provider in Jetty 9.4:
Service endpoint interface:
package org.example.sampleservice;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
#WebService(targetNamespace="http://ws.udc.es/event")
public interface SampleService {
#WebMethod(operationName = "findEvent")
public ServiceEventDto findEvent(#WebParam(name = "eventId") Long eventId) throws InstanceNotFoundException;
}
Service implementation:
package org.example.sampleservice;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
#WebService(endpointInterface = "org.example.sampleservice.SampleService", targetNamespace="http://ws.udc.es/event")
public class SampleServiceImpl implements SampleService {
#Resource
private WebServiceContext ctx;
#WebMethod(operationName = "findEvent")
public ServiceEventDto findEvent(#WebParam(name = "eventId") Long eventId) throws InstanceNotFoundException {
System.out.println("SampleServiceImpl: received eventId " + eventId);
return new ServiceEventDto();
}
}
When I use your original input with <eve:eventId>0</eve:eventId> I observe the following output:
SampleServiceImpl: received eventId null
When I use <eventId>0</eventId> I observe the expected output:
SampleServiceImpl: received eventId 0
If, however, you are expected to accept <eve:eventId> you could also adjust your #WebParam to add targetNamespace as follows:
#WebParam(name = "eventId", targetNamespace="http://ws.udc.es/event") Long eventId
When I change my service provider this way, the output is reversed and <eve:eventId> is no longer null.

Related

Spring boot response filter for restructuring controller response before sending to client

I have a couple of spring boot rest controllers, and I want a standard JSON response structure to be sent to the client.
The standard response will be composed of responseTime, apiResponseCode, status, apiName, response ( which will vary based on the api). See below:
{
"responseTime": "2020-04-19T08:36:53.001",
"responseStatus": "SUCCESS",
"apiResponseCode": "SUCCESS",
"apiName": "PROPERTY_STORE_GET_PROPERTIES",
"response": [
{
"propertyName": "app.name",
"propertyValue": "property-store"
}
]
}
To achieve this, I have created below model class:
package com.example.response.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
public class ApplicationResponse<T> implements Serializable {
private static final long serialVersionUID = -1715864978199998776L;
LocalDateTime responseTime;
Status responseStatus;
ApiResponseCode apiResponseCode;
String apiName;
T response;
public ApplicationResponse(LocalDateTime responseTime, Status status,
ApiResponseCode apiRespCode, String apiName, T response) {
this.responseTime = responseTime;
this.responseStatus = status;
this.apiResponseCode = apiRespCode;
this.apiName = apiName;
this.response = response;
}
// getters and setters
To create a generic response wrapper, I have created below response util class.
import java.time.LocalDateTime;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.response.model.ApplicationResponse;
public class ResponseUtil {
public static <T> ApplicationResponse<T> createApplicationResponse(String
apiName, T response) {
return new ApplicationResponse<>(LocalDateTime.now(),
Status.SUCCESS, ApiResponseCode.SUCCESS, apiName,
response);
}
private ResponseUtil() {
}
}
Now the ask is that my response from controller should get serialized in the standard way. Shown below is my controller method.
package com.example.propertystore.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RestController;
import com.example.constants.ApiResponseCode;
import com.example.constants.Status;
import com.example.exception.ApplicationException;
import com.example.exception.ApplicationExceptionHelper;
import com.example.propertystore.constants.PropertyStoreApiName;
import com.example.propertystore.dto.PropertyDTO;
import com.example.propertystore.entity.Property;
import com.example.propertystore.service.PropertyStoreService;
import com.example.response.ResponseUtil;
import com.example.response.model.ApplicationResponse;
#RestController
public class PropertyStoreControllerImpl implements PropertyStoreController {
#Autowired
PropertyStoreService propertyStoreService;
#Autowired
ApplicationExceptionHelper exceptionHelper;
#Override
public ApplicationResponse<List<PropertyDTO>> getProperties() throws ApplicationException {
ApplicationResponse<List<PropertyDTO>> response = null;
try {
response = ResponseUtil.createApplicationResponse(
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(),
propertyStoreService.getProperties());
} catch (Exception e) {
exceptionHelper.raiseApplicationException( HttpStatus.INTERNAL_SERVER_ERROR, Status.FAILURE,
ApiResponseCode.INTERNAL_SERVER_ERROR,
PropertyStoreApiName.PROPERTY_STORE_GET_PROPERTIES.toString(), null);
}
return response;
}}
With the current implementation what I'll have to do is that in my controllers I will have to transform the response by calling ResponseUtil.createApplicationResponse(). This is going to litter the entire controller methods with the createApplicationResponse() method call.
What I wanted to explore is that if there is any cleaner way of achieving this using servlet filters or AOP?
PS: I tried filter option, but couldn't understand how to proceed around it. Got stuck after retrieving the response.getOutputStream() in doFilter().
Hope someone can help?
Just wrap all your responses into a decorator object.
class ResponseDecorator<T> {
//global.fields (time,code, status.....)
T response;
}
Then wrap this response wrapper into the ResponseEntity
The response.getOutputStream that you used and filters are servlet related classes , and i think you can do that without them.Just make your custom response class and add fields however you want your response. Than in the controller , just return new ResponseEntity(HttpStatus.OK,"your message "):
I don't know if this is the behavior you want.

how to get response from post in javaws playframework 2.5

please help me, i want send json data to some API which use basic auth and i want catch respon from that API. this is my code:
#Inject
WSClient ws;
public Result testWS(){
JsonNode task = Json.newObject()
.put("id", 123236)
.put("name", "Task ws")
.put("done", true);
WSRequest request = ws.url("http://localhost:9000/json/task").setAuth("user", "password", WSAuthScheme.BASIC).post(task);
return ok(request.tojson);
the question is how i get return from ws above and process it to json? because that code still error. i'm use playframework 2.5
.post(task) results in a CompletionStage<WSResponse>, so you can't just call toJson on it. You have to get the eventual response from the completion stage (think of it as a promise). Note the change to the method signature too.
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.fasterxml.jackson.databind.JsonNode;
import play.libs.Json;
import play.libs.ws.WSAuthScheme;
import play.libs.ws.WSClient;
import play.libs.ws.WSResponse;
import play.mvc.Controller;
import play.mvc.Result;
import scala.concurrent.ExecutionContextExecutor;
#Singleton
public class FooController extends Controller {
private final WSClient ws;
private final ExecutionContextExecutor exec;
#Inject
public FooController(final ExecutionContextExecutor exec,
final WSClient ws) {
this.exec = exec;
this.ws = ws;
}
public CompletionStage<Result> index() {
final JsonNode task = Json.newObject()
.put("id", 123236)
.put("name", "Task ws")
.put("done", true);
final CompletionStage<WSResponse> eventualResponse = ws.url("http://localhost:9000/json/task")
.setAuth("user",
"password",
WSAuthScheme.BASIC)
.post(task);
return eventualResponse.thenApplyAsync(response -> ok(response.asJson()),
exec);
}
}
Check the documentation for more details of working with asynchronous calls to web services.

WebService not being produced./Generated

I am trying to deploy a webservice on my localhost, but it doesn't seem to produce the "Endpoint".
I don't know how I messed it up :(
I am using apache cxf 2.7.1 and glassfish 3.1. I even attempted to add ear libraries.
Here is my build path:
and my project explorer looks like this:
I have annotations on both my webservice and webservice interface, as shown below:
Code for webservice interface (I removed the other some parts to make the code shorter)
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import no.solarsoft.venus2.webservice.exception.WebServiceException;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQuery;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQueryParameterKey;
import no.solarsoft.venus2.webservice.queryoptions.QueryParameter;
#WebService()
public interface WebServiceVenus2Interface {
/**
* FETCHING DATA FROM DATABASE
*
*/
#WebMethod
public void Foo(ParticipantQueryParameterKey pqpk);
#WebMethod
public String test();
#WebMethod
public String sayHello(String string) throws WebServiceException;
The code for my web service:
import javax.annotation.Resource;
import javax.jws.WebParam;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import no.solarsoft.venus2.datamanager.CRUDOperation;
import no.solarsoft.venus2.datamanager.DataManager;
import no.solarsoft.venus2.entities.GradeScale;
import no.solarsoft.venus2.enums.ImageType;
import no.solarsoft.venus2.exception.DataAccessException;
import no.solarsoft.venus2.exception.InstanceNotFoundException;
import no.solarsoft.venus2.service.EmailService;
import no.solarsoft.venus2.webservice.exception.ParameterValidationException;
import no.solarsoft.venus2.webservice.exception.WebServiceException;
import no.solarsoft.venus2.webservice.exception.WebServiceFaultBean;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQuery;
import no.solarsoft.venus2.webservice.queryoptions.ParticipantQueryParameterKey;
import no.solarsoft.venus2.webservice.queryoptions.QueryParameter;
// #Stateless()
#javax.jws.WebService(endpointInterface = "no.solarsoft.venus2.webservice.WebServiceVenus2Interface", serviceName = "WebServiceVenus2Service")
public class WebServiceVenus2 implements WebServiceVenus2Interface {
private DataManager dataManager = DataManager.getInstance();
private static final Logger log = Logger.getAnonymousLogger();
#Resource
WebServiceContext wsContext;
#Override
public void Foo(ParticipantQueryParameterKey pqpk) {}
private void logEntered(String login) {
log.info(MessageFormat.format("{0}: ''{1}'' entered web service method ''{2}()''",
WebServiceVenus2.class.getSimpleName(), login, getMethodName()));
}
private String getClientIp() {
MessageContext mc = wsContext.getMessageContext();
HttpServletRequest req = (HttpServletRequest) mc.get(MessageContext.SERVLET_REQUEST);
return req.getRemoteAddr();
}
/**
* Get the method name for a depth in call stack. <br />
* Utility function
*
* #param depth
* depth in the call stack (0 means current method, 1 means call method, ...)
* #return method name
*/
public static String getMethodName() {
final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
return ste[3].getMethodName(); // Thank you Tom Tresansky
}
/**
* FETCHING DATA FROM DATABASE
*/
#Override
public String test() {
String ip = getClientIp();
logEntered(ip);
return "WebService test succeded! Client IP: " + ip;
}
#Override
public String sayHello(String string) throws WebServiceException {
logEntered(null);
if (string == null || string.isEmpty()) {
log.severe("Throwing excetion...");
throw new WebServiceException("String can not be empty or NULL!", new WebServiceFaultBean());
}
log.exiting(WebServiceVenus2.class.getName(), WebServiceVenus2.getMethodName());
return "Hello " + string + "!";
}
and here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
I hope someone can help me. Thanks
I loaded this code nearly verbatim to a dynamic web module in eclipse and deployed to Glassfish4. When deployed (using eclipse "add to server") the WSDL is available at http://localhost:8181/Venus2WebService/WebServiceVenus2Service?wsdl
and the web service endpoint is http://localhost:8181/Venus2WebService/WebServiceVenus2Service
The only jars I included from CXF (not shown in your post) are, from reading WHICH_JARS readme within CXF binary distribution lib dir:
asm-3.3.1.jar
commons-logging-1.1.1.jar
cxf-2.7.17.jar
geronimo-javamail_1.4_spec-1.7.1.jar
geronimo-jaxws_2.2_spec-1.1.jar
jaxb-api-2.2.6.jar
jaxb-impl-2.2.6.jar
neethi-3.0.3.jar
stax2-api-3.1.4.jar
wsdl4j-1.6.3.jar
xmlschema-core-2.1.0.jar
I got the endpoint URL from watching the eclipse console for the server:
2015-09-09T21:45:40.683-0400|Info: Webservice Endpoint deployed WebServiceVenus2
listening at address at http://oc-mbp01.local:8181/Venus2WebService/WebServiceVenus2Service.
Classpath (all in WEB-INF/lib for me):

Java endpoint - perl consumer web service

I've problem with calling java endpoint (code below) from perl client (activePerl 5.16).
Those code snippets are from book Java Web Services Up And Running
package ch01.ts;
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 interface TimeServer {
#WebMethod
String getTimeAsString();
#WebMethod
long getTimeAsElapsed();
}
package ch01.ts;
import java.util.Date;
import javax.jws.WebService;
#WebService(endpointInterface="ch01.ts.TimeServer")
public class TimeServerImpl implements TimeServer {
public String getTimeAsString() {
return new Date().toString();
}
public long getTimeAsElapsed() {
return new Date().getTime();
}
}
package ch01.ts;
import javax.xml.ws.Endpoint;
public class TimeServerPublisher {
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:9876/ts", new TimeServerImpl());
}
}
And the perl consumer:
use SOAP::Lite;
my $url = 'http://127.0.0.1:9876/ts?wsdl';
my $service = SOAP::Lite->service($url);
print "\nCurrent time is: ",$service->getTimeAsString();
print "\nElapsed miliseconds from the epoch: ", $service->getTimeAsElapsed();
When I'm calling the web service I'm having this stack trace:
maj 04, 2013 10:21:40 AM com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit handle
SEVERE: Couldn't create SOAP message. Expecting Envelope in namespace http://schemas.xmlsoap.org/soap/envelope/, but got http://schemas.xmlsoap.org/wsdl/soap/
com.sun.xml.internal.ws.protocol.soap.VersionMismatchException: Couldn't create SOAP message. Expecting Envelope in namespace http://schemas.xmlsoap.org/soap/envelope/, but got http://schemas.xmlsoap.org/wsdl/soap/
at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(Unknown Source)
I think that the soap version is the problem, above example is from 1.1, when I've change the client code to
my $service = SOAP::Lite->service($url)->soapversion('1.2');
then different error is throw
com.sun.xml.internal.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/soap+xml; charset=utf-8 Supported ones are: [text/xml]
I need help with either dealing with envelope problem or content-type. I will be grateful for any directions, code and anything else that could help.
I am not quite sure of Perl->Soap API, But for first case where client version is 1.1 may be you need to mention namespace also somewhere.
May be like
server->setNamespace() //or
SOAP::Lite->service($url,"<namespace>"); //please search for perl web service client examples
And for second case(1.2) service is expecting text and your api sends soap encoding or something.
Refer http://www.herongyang.com/Web-Services/Perl-SOAP-1-2-Unsupported-Media-Type-application-soap.html
This may be helpful
my $client = SOAP::Lite->new()
->soapversion('1.2')
->envprefix('soap12')
->default_ns('http://xmlme.com/WebServices')
->on_action( sub {join '/', #_} )
->readable(true)
->proxy('http://www.xmlme.com/WSShakespeare.asmx');
and
http://www.herongyang.com/Web-Services/Perl-SOAP-1-2-Request-Differences-SOAP-1-1-and-1-2.html
Hope it helps

Web Service testing

I made web services using JAX-WS. Now I want to test using a web browser, but I am getting an error. Can somebody explain me please help.
My Service class:
package another;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
#WebService(name = "WebService")
public class WebServiceTest {
public String sayHello(String name) {
return "Hello : " + name;
}
public static void main(String[] args) {
WebServiceTest server = new WebServiceTest();
Endpoint endpoint = Endpoint.publish(
"http://localhost:9191/webServiceTest", server);
}
}
I run this class as simple Java program.
And I can see the WSDL in my browser at http://localhost:9191/webServiceTest?wsdl.
And I am trying to call this using the URL http://localhost:9191/webServiceTest?sayHello?name=MKGandhi, but I am not getting any result.
What is wrong here?
I can't tell you why it is not possible to test it in browser.
But at least I can tell you how to test it from your code, cause your webservice works:
package another;
import javax.jws.WebService;
#WebService
public interface IWebServiceTest {
String sayHello(String name);
}
package another;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class Main {
public static void main(String[] args) throws Exception {
String url = "http://localhost:9191/webServiceTest?wsdl";
String namespace = "http://another/";
QName serviceQN = new QName(namespace, "WebServiceTestService");
Service service = Service.create(new URL(url), serviceQN);
String portName = "WebServicePort";
QName portQN = new QName(namespace, portName);
IWebServiceTest sample = service.getPort(portQN, IWebServiceTest.class);
String result = sample.sayHello("blabla");
System.out.println(result);
}
}
You try and test your webservice by using the url http://localhost:9191/webServiceTest?sayHello?name=MKGandhi
Just try this url http://localhost:9191/webServiceTest/sayHello?name=MKGandhi
it should work fine :)
in your url "http://localhost:9191/webServiceTest?sayHello?name=MKGandhi"
try changing the localhost by your ip address.
example : "http://198.251.234.45:9191/webServiceTest?sayHello?name=MKGandhi"

Categories