I have a WSDL schema link. With NetBeans I generated classes from this schema. But I can't understand, how to use it to send request to server? There is a XXXImplService extends Service class generated by NetBeans, should I use it? How?
As I think, I need just to create objects (which match WSDL methods and classes), set necessary properties and somehow transform this objects into a text of request, then send it with and get text response, which I can transform into classes. Is this true?
of course you have to use the WSDL, follow below steps for a complete client app for a Java web service (JAX-WS):
assuming you have a Web Service like this:
#WebService
public class Hello {
private String message = new String("Hello, ");
public void Hello() {}
#WebMethod
public String sayHello(String name) {
return message + name + ".";
}
}
Uses the javax.xml.ws.WebServiceRef annotation to declare a
reference to a web service. #WebServiceRef uses the wsdlLocation
element to specify the URI of the deployed service’s WSDL file:
#WebServiceRef(wsdlLocation="http://localhost:8080/helloservice/hello?wsdl")
static HelloService service;
Retrieves a proxy to the service, also known as a port, by invoking
getHelloPort on the service.
Hello port = service.getHelloPort();
The port implements the SEI defined by the service.
Invokes the port’s sayHello method, passing to the service a name.
String response = port.sayHello(name);
EDIT: (request in comments) if the web service request for basic authentication and want to pass a username and password you can pass them like this (there are other ways also):
import java.net.Authenticator;
import java.net.PasswordAuthentication;
Authenticator authenticator = new Authenticator()
{
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("usr", "pass".toCharArray());
}
};
Authenticator.setDefault(authenticator );
however if you want authentication in application level not on basic
HTTP this link can be useful.
You have to implement your code in this generated service impl and web method now. So when you will be calling the service end point and a specific method, through a web service client ( SOAP UI etc), these generated classes will take the call and route through service impl, to your implementation.
This tutorial will help you to do it step by step. Since you have already created stub classes, skip the first part. Focus on "Web service invocation" section.
http://www.ibm.com/developerworks/webservices/library/ws-apacheaxis/index.html?ca=dat
Related
I have a service definition using Spring annotations. Example (source):
#RequestMapping(value = "/ex/foos/{id}", method = GET)
#ResponseBody
public String getFoosBySimplePathWithPathVariable(
#PathVariable("id") long id) {
return "Get a specific Foo with id=" + id;
}
The question is whether spring (or another library) can auto-create a remote implementation (client) of the same API without the need to manually type paths, method type, param names, etc. (like needed when using RestTemplate)?
Example of an such a client usage:
FooClient fooClient = new FooClient("http://localhost:8080");
String foo = fooClient.getFoosBySimplePathWithPathVariable(3l);
How can I get to such a client "generated" implementation"?
You are probably looking for Feign Client. It does everything you need: calling one service via HTTP is similar to calling method of Java interface. But to make it work you need Spring Cloud, standard Spring framework doesn't have this feature yet.
You can generate it using Swagger Editor. You shoud just define the path of the resources and then it'll generate for you the client for almost any language of your choice
I'm trying to understand how Jax-WS web services work but can't find any resources on the specifics of them. By way of example:
I create a very simple Java web service using Jax-WS annotations, like so
#WebService(name = "MyService", serviceName = "MyService", portName = "MyServicePort")
public class MyService {
private int val;
public MyService() {
val = 0;
}
#WebMethod(action = "setVal")
public void setVal(#WebParam(name = "arg") int arg) {
val = arg;
}
#WebMethod(action = "getVal")
public int getVal() {
return val;
}
}
If I generate a web service from this (using WS-Gen, say), build a client and make the following calls from a single client: setVal(5), getVal(), what value will be returned to the client? Why?
What about if client A calls setVal(5), and client B calls getVal(), what value will be returned to the client? Why?
Naturally I could build a web-service myself and test it, but I was hoping for an explination to go with the answer. Does Jax-Ws create a new instance of the annotated class for each request? Does it somehow map the same source to the same annotated class instance? Does it just map all requests to a singleton instance of the annotated class? Is there a finite pool of annotated class instances that picked from in some fashion?
Web Services are stateless by default because of the underlying HTTP protocol. The server processes each web service request as a new interaction even though it is from the same client
Normally, a JAX-WS Web service is stateless: that is, none of the
local variables and object values that you set in the Web service
object are saved from one invocation to the next. Even sequential
requests from a single client are treated each as independent,
stateless method invocations.
There are Web service use cases where a client may want to save data
on the service during one invocation and then use that data during a
subsequent invocation. For example, a shopping cart object may be
added to by repeated calls to the addToCart web method and then
fetched by the getCart web method. In a stateless Web service, the
shopping cart object would always be empty, no matter how many
addToCart methods were called. But by using HTTP Sessions to maintain
state across Web service invocations, the cart may be built up
incrementally, and then returned to the client.
Enabling stateful support in a JAX-WS Web service requires a minimal
amount of coding on both the client and server.
http://docs.oracle.com/cd/E17904_01/web.1111/e13734/stateful.htm
DISCLAIMER: I did search exhaustively for an answer to this question, and yes, I did find this other question: https://stackoverflow.com/questions/10315728/how-to-send-parameters-as-formparam-to-webservice . But firstly, that question is asking about Javascript, while I am asking about Java, and secondly, it has no answers anyway. So on to the question...
With RESTful services, passing #QueryParams into an #GET service is fairly easy, as you can simply append variables name/value pairs to a URL and use it to hit the server from within the program. Is there a way to do this with #FormParams as well?
For example, let's say I have the following RESTful service:
#POST
#Produces("application/xml")
#Path("/processInfo")
public String processInfo(#FormParam("userId") String userId,
#FormParam("deviceId") String deviceId,
#FormParam("comments") String comments) {
/*
* Process stuff and return
*/
}
... and let's say I also have another method somewhere else in my program like this:
public void updateValues(String comments) {
String userId = getUserId();
String deviceId = getDeviceId();
/*
* Send the information to the /processInfo service
*/
}
How can I perform the commented out action in the second method?
NOTE: Assume these methods are not in the same class or package. Also assume that the RESTful service is hosted on a different server than the machine you are running your method from. As such, you must access the method and pass the values in in a RESTful way.
Thank you for your help!
Using #FormParam you can bind form parameters to a variable.You can find a sample here.
Secondly ,In order to call rest service internally form your java method code you will have to use jersey client.Example code can be found here.
You can pass form parameters using jersey client form as follows.
Create form
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(UriBuilder.fromUri("http://localhost:8080/api").build());
Form f = new Form();
f.add("userId", "foo");
f.add("deviceId", "bar");
f.add("comments", "Device");
pass it to Restful method.
service.path("processInfo").accept(MediaType.APPLICATION_XML).post(String.class,f);
reference
We have been provided with a wsdl and xsd schema by a company we are working with via email. The web-services we are interfacing with are accessed through a IPsec tunnel. There are local references(on their end) in the published WSDL which means we cannot consume it.
1st question: Is this a common setup? I thought the point of having a WSDL was not only to define the contract but to also expose the service to consumers.
I can easily generate client/server code off of the provided WSDL using wsimport, wsconsume, etc.. I know when my generated client makes a call to my generated service it produces the correct message I need.
2nd Question: Is there an easy way to route this to a different soap address?
I just want to be able to do something like:
SalesTaxService svc = new SalesTaxService();
SalesTax tax = svc.getSalesTaxPort()
tax.getRate("NY");
But not use the soap address defined in the WSDL. I would like to avoid writing a bunch of dispatch clients for each method.
Am I missing something?
*In response to skaffman:
This is what was generated. It defaulted to wsdlLocation as a name shrug
#WebServiceClient(name = "SomeService")
public class SomeService_Service extends Service {
public SomeService_Service(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public SomeService_Service(URL wsdlLocation) {
super(wsdlLocation, new QName("urn:some_service", "SomeService"));
}
}
I thought the point of having a WSDL
was not only to define the contract
but to also expose the service to
consumers.
No, WSDL is purely a descriptive tool, it has no real runtime role. The web service operates completely independently of the WSDL. It's not uncommon for the WSDL to not be exposed.
Is there an easy way to route this to
a different soap address?
That depends entirely on what web service implementation you're using, and you don't say, although I'm guessing JAX-WS. If that's the case, the artifacts that JAX-WS's tools generate allow you to pass in the URL to the client stub constructors, I think.
So I figured out why I was having a problem. I was assuming that the wsdlLocation had to be the WSDL that the actual service was publishing. This of course is not the case. The solution is to package a local WSDL with the correct SOAP:Address for the actual service into the client.
edit
I found out that you can alter the endpoint address programmatically without having to alter the actual WSDL:
HelloService service = new HelloService (
this.getClass().getResource("originalHello.wsdl"),
new QName("http://example.org/hello", "HelloService "));
HelloPort proxy = service.getHelloPort();
Map<String, Object> ctxt = ((BindingProvider)proxy ).getRequestContext();
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://new/endpointaddress");
proxy.sayHello("Hello World!");
Credit goes to : Jianming Li
I am using latest Apache CXF to create a webservice. I have configured ws-security using org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor. In my passwordCallbackClass I can access the user or identifier by calling getIdentifier() method of org.apache.ws.security.WSPasswordCallback class.
I am also using spring for the whole setup.
I would like to know how to access the identifier any where else in the code? I could think of using ThreadLocal in my passwordCallbackClass? Another way is define to an identifier property in all my service method parameters but that would mean client need to pass the identifier twice, one in the security block and again in the service call?
Edit
My service class looks like this and I need to read the Identifier in sayHi method.
#WebService(endpointInterface = "com.webservice.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
return "Hello " + text;
}
}
My Password callback method is this where I can get the Identifier.
public void handle(Callback[] callbacks) throws IOException,UnsupportedCallbackExceptio {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.getIdentifier();
}
I used ThreadLocal in my Password callback method to store the Identifier. I then access the ThreadLocal anywhere in the code to know the identifier.
Define "any where else in the code"? Are you talking about in other interceptors? In your server implementation? Are you using JAXWS or the simple frontend? Etc...
If using jaxws and you want it in your server impl, the JAXWS WebServiceContext has a getUserPrincipal() method that would just be a principal that WSS4J creates after you validate the user.
Pretty much anywhere else (or even in the server impl using the context), you can do something like:
message.get(SecurityContext.class).getUserPrincipal();
to achieve the same result.