created the web service source using WSDL in netbeans IDE. Then in servlet class generated code to call web service method. I got code like this:
private void getSomething() {
com.bla.bla.SomeService service = new com.bla.bla.SomeService();
QName portQName = new QName("http://bla.com/test/services", "SomeServiceSoap");
String req = "<getSomething xmlns="\url\"><a id=\"5\"/></getSomething>";
try {
Dispatch<Source> dispatch = null;
dispatch = service.createDispatch(portQName, Source.class, Service.Mode.PAYLOAD);
Source result = dispatch.invoke(new StreamSource(new StringReader(req)));
} catch (Exception ex) {
ex.printStackTrace();
}
}
But when I call this method, I am getting an Exception: javax.xml.ws.soap.SOAPFaultException: System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP header SOAPAction: .
How to solve this problem? Any help is appreciated! thanks!
That error means, though there is some webservice running at the endpoint http://bla.com/test/services there is no operation is available on that purticular service.
OR
client didnt supply any operation to invoke on SimpleSoapService
Related
I am able to call soap service and getting the response from soap client does means connectivity is okay. But the request data values are not mapping to external system request. and we both are using same package and class names.
Please find the code as below:
UserListResponse response = null;
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "UserList")
#ResponsePayload
public UserListResponse UserListRequest(#RequestPayload UserListRequest request) throws Exception {
System.out.println("Enters into UserList()");
try {
//Client call
UserServicesLocator locator = new UserServicesLocator();
UserServicesSoapStub stub = (UserServicesSoapStub) locator.getUserServicesSoap();
response = stub.userList(request);//here the request data values not mapping at external system side
} catch(Exception e) {
e.printStackTrace();
}
return response;
}
Note: Client classes are able to generated using wsdl and in that client classes having pojo structure with serialization and de-sterilization methods.
Can anyone please suggest on this issue.
I'm using ResteasyClient to make a REST client to my another service A. Say, service A throws an exception CustomException with a message : Got Invalid request.
Here is how I am using the Client:
public Response callServiceA(final String query) {
ResteasyClient client = new ResteasyClientBuilder().build();
String link = "abc.com/serviceA";
ResteasyWebTarget target = client.target(link).path("call");
Form form = new Form();
form.param("query", query);
Response response;
try {
String data =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
response = Response.ok().entity(data).build();
} catch (Exception e) {
String message = e.getMessage();
e.printStackTrace();
response = Response.serverError().entity(e.getMessage()).build();
} finally{
client.close();
}
return response;
}
However, when I print the stacktrace, I'm unable to find my custom error message. I can just see the message as HTTP 400 Bad Request.
Could you please suggest me how to access the error message?
NOTE: I am able to get the error message when I call the serviceA using the restClient. Hence, I dont think there is an issue with the service.
Don't deserialize the response straight to a String.
String data = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
When you do this (and there is a problem), you just get a client side exception, which doesn't carry information about the response. Instead just get the Response with the overloaded post method
Response response = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE));
Then you can get details from the Response, like the status and such. You can get the body with response.readEntity(String.class). This way you don't need to handle any exceptions. Just handle conditions based on the status.
Do note though that the Response above is an inbound Response, which is different from the outbound Response in your current code. So just make sure not to try and send out an inbound Response.
Also see this answer and it's comments for some design ideas.
I have an error and I am getting confuse, I have created a simple Java EE 7 project using Jersey.
I am returning this class in my Rest Rervice:
#XmlRootElement
public class LocationDTOx {
private Long id;
private String tittle;
private String description;
private Long parent;
//Getter and setters...
And in my service class i Have:
#Path("/location")
public class LocationService {
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/findlocation")
public LocationDTOx findLocation() {
System.out.println("findlocation");
try {
LocationDTOx x = new LocationDTOx();
x.setDescription("Description");
x.setId(0l);
x.setParent(null);
x.setTittle("Tittle ...");
return x;
} catch (Exception ex) {
Logger.getLogger(LocationService.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
I am 100% sure that my rest it is working , if I put this in my browser:
http://localhost:8080/BIReportL-war/rest/location/findlocation
I get this Json String:
{"description":"Description","id":0,"tittle":"Tittle ..."}
The deal is in my angular code, the code where I am calling the rest service from angular it is getting executed but it is just giving me the error part:
app.controller('questionsController', function ($scope, $http) {
//var url = "http://localhost:8080/BIReportL-war/rest/location/findlocation";
//var url = "http://www.w3schools.com/angular/customers.php";
var url = "http://127.0.0.1:8080/BIReportL-war/json.json";
$http.get(url)
.success(
function (data, status, headers, config) {
alert("success");
})
.error(function(data, status, headers) {
alert('Repos status ' + status + ' --- headers : ' + headers);
})
.finally(
function() {
});
});
I have with comments another local URL to a dummy json file that I can access it by that browser, and also I get the same result an error, the weird thing is that I tried with this rest public json file:
http://www.w3schools.com/angular/customers.php
And I get the success !! I don't know why, what I am doing or what I have wrong, I mean when I try with my local rest service, I see that it is getting called in the logs, that is a fact, but the angular client is getting into an error.
Thanks in advance for your help !
I am using:
*Glassfish V4
*Angular
Well, was about the CORS Issue I just put my rest as below, so here is the SOLUTION:
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/findlocation")
public Response findLocation() {
System.out.println("findlocation");
try {
LocationDTOx x = new LocationDTOx();
x.setDescription("Description");
x.setId(0l);
x.setParent(null);
x.setTittle("Tittle ...");
return Response.ok()
.entity(x)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT")
.build();
} catch (Exception ex) {
Logger.getLogger(LocationService.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
If AngularJS is accessing your local REST API, the fact that you're running it in a browser on a different port, it counts as a different origin, per the rules of CORS (separate port means separate origin).
Two pages have the same origin if the protocol, port (if one is
specified), and host are the same for both pages.
For your Access-Control-Allow-Origin response header, either set it to all via *, or specify the alternate ports explicitly. This has to do with the fact that your browser (and AngularJS) are attempting to play by the rules, which you can find on MDN's page on same origin policy.
These "rules" don't apply when you load the resource directly in your browser, as the origin (page your browser is loading from) is the same port, as you're loading just the resource, at that origin (plus port).
[Edit]
The CORS standards included adherence to certain response headers, such as Access-Control-Allow-Origin and Access-Control-Allow-Methods.
References:
MDN's page on access control
HTML5Rocks.com tutorial on CORS
[/Edit]
Your Jersey service is using GET (#GET) while your Angular client is using POST ($http.post(url)).
Change the Angular code to $http.get and you're good to go.
Your example of http://www.w3schools.com/angular/customers.php is working because it responds to both POST and GET, however for your scenario GET is clearly the correct HTTP verb.
Did you try to use relative url? var url = "/BIReportL-war/json.json";
Can you post here the entire error?
I agree with #pankajparkar it might be a CORS problem.
(Sorry for posting this 'answer', I don't have enough points for comments)
I've found a read a number of threads on here about how to retrieve the XML response from a JAX-WS client. In my case, the client is generated from the WSDL via Oracle's JDeveloper product and is going to invoke a Document/Literal service endpoint that was written in .NET. What I want to do is obtain the XML response from the call FROM the calling client, not from inside a handler.
The closest thread that I saw to this issue was:
http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml
I don't think I want to generate a Dispatch call because the endpoint's XML schema for the SOAP packet is rather complex, and the automatic proxy makes the call trivial. Unless there is some other way to populate the generated bean(s) and then invoke some method that simply produces the XML and I then make the call?
private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SOAPMessage soapMessage = messageContext.getMessage();
try {
soapMessage.writeTo(baos);
String responseXml = baos.toString();
log.debug("Response: " + responseXml );
PaymentGatewayXMLThreadLocal.set(responseXml);
} catch (SOAPException e) {
log.error("Unable to retrieve SOAP Response message.", e);
} catch (IOException e) {
log.error("Unable to retrieve SOAP Response message.", e);
}
}
My thought was to store the response to the call in a ThreadLocal inside the handler and then read it after the call. Is that reasonable? So after the handler does the above code in the handleMessage and handleFault, the client calling code invokes this method:
#Override
public String getSOAPResponseXML(Object clientstub) {
String returnValue = PaymentGatewayXMLThreadLocal.get();
return returnValue;
} // getSOAPResponseXML
It appears there may be another way after all. After reading jax-ws-handlers, I saw that the handler can introduce an Application scoped variable. I changed the handler to do this:
private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
String xml = getSOAPMessageXml(messageContext);
// YourPayXMLThreadLocal.set(xml);
// put it into the messageContext as well, but change scope
// default of handler Scope, and client can't read it from responsecontext!
messageContext.put(SOAP_RESPONSE_XML, xml);
messageContext.setScope(SOAP_RESPONSE_XML, MessageContext.Scope.APPLICATION );
} // storeSOAPMessageXml
The client just reads it like this:
#Override
public String getSOAPResponseXML(Object clientstub) {
String returnValue = null;
// works (assuming a threadlocal is ok)
// returnValue = YourPayXMLThreadLocal.get();
BindingProvider bindingProvider = (BindingProvider) clientstub;
// Thought this would work, but it doesn't - it returns null.
// Map<String, Object> requestContext = bindingProvider.getRequestContext();
// String returnValue = (String) requestContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);
// this works!!
Map<String, Object> responseContext = bindingProvider.getResponseContext();
System.out.println("has key? " + responseContext.containsKey(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML));
returnValue = (String) responseContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);
return returnValue;
} // getSOAPResponseXML
If you just want to see the request, you can use the system property
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
If you actually want to do something with the request, then a handler seems the natural solution. Perhaps use the request context to pass values to the handler? On the client:
((BindingProvider) port).getRequestContext().put("KEY", "VALUE");
In the handler:
String value = (String) messageContext.get("KEY");
Unfortunately, the only way to get the XML before sending it and without using Message Handlers is to marshall it your self (see JAXB). This will give you an XML representation of the data, however it might not LOOK exactly the same as the message sent to the WS. Differences might arise in the way that namespaces are used, ect., but most importantly you will not get the whole SOAP envelope, just the XML data for the header you choose to marshall.
I wrote the following code to implement a Java web service that communicates with an application written in another language on the same host:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
#WebService(name = "MyWebService")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class MyWebService {
#WebMethod(operationName = "methodName", action = "urn:#methodName")
#WebResult(name = "result", partName = "output")
public String methodName(#WebParam(name = "param1", partName = "input") String param1,
#WebParam(name = "param2", partName = "input") String param2){
// ...do something
return "You called this service with params: " + param1 + "," + param2;
}
Since requirements are not to use an application server to expose the web service I instantiated the service from another class as follows:
Endpoint endpoint = Endpoint.create(new MyWebService());
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
Questions:
1) Which is the simplest way to secure this service with username and password considering the architecture of this project?
Any code sample would be greatly appreciated.
2) I made some research and found the use of SOAPHandler and I think it would work for me.
In the case of using the SOAPHandler class how do I add headers to the message to require authentication from the client?
Thank you in advance
thanks so much for the response that's the direction I'm following too but
when I check any of the headers for example:
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
Iterator<SOAPElement> iterator = header.getAllAttributes();
I get a nullpointer exception...any ideas?
I did a working program. Just to add to what you already found out, following is a way to use handler
Endpoint endpoint = Endpoint.create(new MyWebService());
Binding binding = endpoint.getBinding();
List<Handler> handlerChain = new ArrayList<Handler>(1);
handlerChain.add(new MyHandler());
binding.setHandlerChain(handlerChain);
URL url = new URL("http://localhost:7777/MyWebService");
endpoint.publish(url.toString());
MyHandler is class extending Handler interface. Alternately, you can use #HandlerChain annotation which will need an xml configuration file for handlers. Configure this for incoming messages only
public class MyHandler implements SOAPHandler{
#Override
public Set<?> getHeaders() {
// TODO Auto-generated method stub
return null;
}
#Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
#Override
public boolean handleFault(MessageContext context) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean handleMessage(MessageContext context) {
System.out.println("Hehehe the handler");
SOAPMessageContext soapContext = (SOAPMessageContext)context;
try {
SOAPHeader header = soapContext.getMessage().getSOAPPart().getEnvelope().getHeader();
//Check there if the required data (username/password) is present in header or not and return true/false accordingly.
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
From the client side also, if your client is using JAB-WS, you will have to use client handlers. Following is a typical JAX-WS client invocation example
Dispatch<Source> dispatch = … create a Dispatch<Source>
dispatch.getBinding().setHandlerChain(chain)
Source request = … create a Source object
Source response = dispatch.invoke(request);
Here the handler in chain will add header to outgoing request. Configure this for Outgoing messages only.
What you did is fair enough.
Concerning the authentication you can just expose a method for passing user name and password as login credentials.
Once the user has provided the correct credentials the user has been authenticated.
Note: Now you must maintain session data and make sure that an incoming request is from an authenticated user. The Endpoint just deploys internally a lightweight http server. You must design you web service implementation to keep "state" among requests.
You have 2 more options.
Do the authentication at the SOAP level. I would not really recomend
it. But if you do, note that the Endpoint does not deploy a
WSDL. So you must communicate exactly to the client connecting,
the SOAP header you expect. It is possible though to write a WSDL by
yourself and "attach" it to the Endpoint.
Do the authentication at the http request level. I.e. add a token or
cookie to the http request. To be honest I do not remember if this
is easy using the Endpoint