WebService Client in Java - java

I have the following problem: I am completely new to java EE (know only about servlets and JSPs) and especially web services.
I need to develop a client for a web service (it needs to query the service for useful information once in a minute).
In my mind this client would be a simple java-SWing-based program, which would query the web service through simple Socket when the application client runs. How can that be done?
Is it possible to do in that way? If not, which is the easiest way to create such a client?

I would suggest using Apache CXF. Simple and powerful framework.
And yes, that is possible to implement what you said using this framework. Just read tutorials and play around for a bit with it.

Inorder to connect to a web service using a java client follow the below mentioned steps:
1. Get the URL in which the webservice is hosted. This is usually of the fomat http://<IP_OF_SERVER>:<PORT_OF_SERVER>/<WEB_APP_NAME>?wsdl
2. Get the qualified name of the service:
// 1st arg is the service URI
// 2nd is the service name published in the WSDL
QName qname = new QName(<Service_URI>, <SERVICE_NAME_PUBLISHED_WSDL>);<br/>
3. Create a factory for the service:
Service service = Service.create(url, qname);
4. Extract the endpoint interface, the service "port":
<Port_Class_Name> eif = service.getPort(<Port_Class_Name>);
5. Now use the methods on the Port, which are the actual methods in your webservice.

You might want to try REST Webservice, try Jersey REST (or others). With rest you can connect it with http connection (GET and POST).

Inorder to connect to a web service using a java client follow the below mentioned steps:
1.URL wsdlUrl = new URL("your wsdl url);
2.QName qname = new QName("targetNamespace in ur wsdl file","service name in your wsdl file");
Service service = Services.create(wsdlUrl,qname);
4.suppose getData() is your SEI
GetData data = (GetData)service.getPort(GetData.class);
5.call the your methods using data object
ex:data.getId(String name); this will return your response

Related

How to pass user session to a REST webservice

I am making a REST webservice call to a protected webservice from a java application. The application is also protected so that I need to login to the application for accessing it. Actually when I invoke the webservice call, I am getting the LDAP login URL as the response as below instead of expected result from the webservice.
"https://login-stage.oracle.com:443/oam/server/obrareq.cgi?"
Looks the webservice is expecting the user session to be passed. Is there anyway we can pass the user session in the REST webservice client call? Here is my code below.
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(REST_URI);
restResponse = getResponse(service);
Please suggest an approach for it.
Since you are calling a REST Service there shouldn't be a session based authentication.
Maybe have a look here. RESTful Authentication
If I understand your question correctly, this is not possible or not RESTful.
A RESTful webservice does not keep any session at all, in fact this is one of the strength of this design pattern.
What you can do is, to add user credentials to the requests. The link provided by questionare is a very good starting point and offers some more options.

Webservice communication between Java EE applications

I have two Java EE applications on two separate application servers. One of them already contains a working EJB. I want to be able to communicate with this EJB from the other application by using a JAX-WS webservice (the communication has to work between different application servers and different server versions, so remote EJB call is no option). It is no problem to expose the server api to the client application.
The server side is quite clear, adding #Webservice annotation seems to work quite well. But i wonder what is the best way to build the client: I don't really want to generate the client stub from the wsdl (which itself has been generated from the ejb code by the container in my case) and pack all these generated classes into the client ear - but this seems to be the only way i can make use of #WebServiceRef annotations.
The alternative to make a dynamic proxy myself with the help of the static methods of javax.xml.ws.Service (sth. like service=Service.create() and service.getPort()) is not recommended by the Spec and "container providers are not required to support managed Service Instances created using these methods".
But that is exactly sth. that I want to use:
Is there a way to get a dynamic proxy injected in my code, managed by the application server? Or is the only way to get a managed webservice client instance to be done with generated client stub classes?
Read JAX-WS 2.2 spec, Chapter 4: Client APIs.
1. Static Client Generation
Is really the simplest way to work with JAX-WS. From a web services perspective, the WSDL is the interface AND the connection properties. Even if you choose not to work with it physically, you still need to know it in a logical sense to make meaningful SOAP calls.
Note from JAX-WS spec: An Endpoint that uses the SOAP 1.1/HTTP binding MUST
make its contract available as a WSDL 1.1 document at the publishing address suffixed with ?WSDL or ?wsdl
2. Dynamic Client Programming
Is there a way to get a dynamic proxy injected in my code, managed by the application server?
This approach involves dynamic programming against the JAX-WS API to connect to a web service either with or without using WSDL. There's no way to just "inject" a dynamic proxy out of nowhere. You need to construct & configure one with the SEI's port URLs. The WSDL document is the standard place to store such configuration information, although it is possible to avoid it and to programmatically insert the info.
2A) Dynamic programming with WSDL:
javax.xml.ws.Service service = Service.create(
new URL("http://example.org/stocks.wsdl"),
new QName("http://example.org/stocks", "StockQuoteService"));
com.example.StockQuoteProvider proxy = service.getPort(portName,
com.example.StockQuoteProvider.class)
javax.xml.ws.BindingProvider bp = (javax.xml.ws.BindingProvider)proxy;
Map<String,Object> context = bp.getRequestContext();
context.setProperty("javax.xml.ws.session.maintain", Boolean.TRUE);
proxy.getLastTradePrice("ACME");
Advantages over (1): can dynamically dynamically change the WSDL doc after app is deployed, provided such changes do not affect the java interface to client.
i.e. very little benefit to you. Your WSDL is static. Whilst you could point your client to <service endpoint URL>?wsdl to dynamically lookup, this means you need to manually configure <service endpoint URL> AND that leaves little else that can change in the SEI/WSDL without impacting your client logic.
2B) Dynamic programming without WSDL:
String endpointUrl = ...;
QName serviceName = new QName("http://example.org/wssample/echo/", "EchoService");
QName portName = new QName("http://example.org/wssample/echo/", "EchoServicePort");
/** Create a service and add at least one port to it. **/
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
/** Create a Dispatch instance from a service.**/
Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);
/** Create SOAPMessage request. **/
// compose a request message
MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
// Create a message. This example works with the SOAPPART.
SOAPMessage request = mf.createMessage();
SOAPPart part = request.getSOAPPart();
// Obtain the SOAPEnvelope and header and body elements.
SOAPEnvelope env = part.getEnvelope();
SOAPHeader header = env.getHeader();
SOAPBody body = env.getBody();
// Construct the message payload.
SOAPElement operation = body.addChildElement("invoke", "ns1",
"http://com/ibm/was/wssample/echo/");
SOAPElement value = operation.addChildElement("arg0");
value.addTextNode("ping");
request.saveChanges();
/** Invoke the service endpoint. **/
SOAPMessage response = dispatch.invoke(request);
Advantage (not really): can eventually get it to carry out same behaviour as above.
Disadvantages: Complex programming. Non-standard configuration (outside of WSDL). Need to avoid hard-coding settings. Brittle to interface changes. Manually synchronising settings between server and client - easy to omit something, extremely difficult to debug.
Answer:
Go back to (1). Generate a client stub from the WSDL. Use it as an interface contract - it should be designed well and not change.
Then spend the time you save solving real problems... ;) ;)

What's a good Java library for dynamic SOAP client operations?

I've been searching for SOAP client libraries for Java and have found a plethora of libraries based on the idea of building stub and proxy classes based on a WSDL. I'm interested in allowing the user to enter a WSDL at runtime, parsing the WSDL, then allowing the user to perform operations on the Web Service.
Does anyone know of a good SOAP client library which will allow this runtime use? Or is there a way I can use the axis2 wsdl2java functionality to build stubs into the classloader and use them at runtime?
Later than never. :)
You should achieve that in two steps:
1) parse the WSDL informed by the user to retrieve the available operations. Refer to this question to know how to do this in a simple way.
2) Create a dynamic client to send a request using the selected operations. It can be done by using the Dispatch API from Apache CXF.
Build the Dispatch object for the dynamic client (It can be created on the fly by informing web service endpoint, port name, etc):
package com.mycompany.demo;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class Client {
public static void main(String args[]) {
QName serviceName = new QName("http://org.apache.cxf", "stockQuoteReporter");
Service s = Service.create(serviceName);
QName portName = new QName("http://org.apache.cxf", "stockQuoteReporterPort");
Dispatch<DOMSource> dispatch = s.createDispatch(portName,
DOMSource.class,
Service.Mode.PAYLOAD);
...
}
}
Construct the request message (In the example below we are using DOMSource):
// Creating a DOMSource Object for the request
DocumentBuilder db = DocumentBuilderFactory.newDocumentBuilder();
Document requestDoc = db.newDocument();
Element root = requestDoc.createElementNS("http://org.apache.cxf/stockExample", "getStockPrice");
root.setNodeValue("DOW");
DOMSource request = new DOMSource(requestDoc);
Invoke the web service
// Dispatch disp created previously
DOMSource response = dispatch.invoke(request);
Recommendations:
Use ((BindingProvider)dispatch).getRequestContext().put("thread.local.request.context", "true"); if you want to make the Dispatch object thread safe.
Cache the Dispatch object for using later, if it is the case. The process o building the object is not for free.
Other Methods
There are other methods for creating dynamic clients, like using CXF dynamic-clients API. You can read in project's index page:
CXF supports several alternatives to allow an application to
communicate with a service without the SEI and data classes
I haven't tried that myself but should worth giving it a try.

Invoking a web service. Need the missing link

Can someone fill in the missing link in the code below?
First way:
The web service interface file is HappyService.
JaxWSProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInterceptors().add(new LoggingInInterceptor());
factory.getInterceptors().add(new LoggingOutInterceptor());
//MISSING LINK. Where does HappyService.class come from? I don't have it
factory.setServiceClass(HappyService.class);
factory.setAddress("http://......../happyService");
//Again how do I get HappyService?
HappyService client = (HappyService) factory.create();
Second way:
String UrlString = "Your WSDL URL";
String nameSpaceUri = "urn:Foo";
String serviceName = "MyHelloService";
String portName = "HelloIFPort";
URL helloWsdlUrl = new URL(UrlString);
ServiceFactory serviceFactory = ServiceFactory.newInstance();
Service helloService =
serviceFactory.createService(helloWsdlUrl,
new QName(nameSpaceUri, serviceName));
//Where did dynamicproxy.HelloIF come from? This code won't compile as that file does not exist anywhere
dynamicproxy.HelloIF myProxy =
(dynamicproxy.HelloIF)
helloService.getPort(
new QName(nameSpaceUri, portName),
dynamicproxy.HelloIF.class);
System.out.println(myProxy.sayHello("Buzz"));
Anyone that has a clue as to where these interface classes come from and how they are generated please let me know. It looks like the only way I can do an web service invocation is by writing the SOAP request by hand and I really don't want to do that as it can get very large and error prone.
There are many tools that generate webservices Java classes from WSDL definition files.
You could try JAXB, which is the standard Java tool for this task.
An other possibility is Axis, which a level higher.
You need a SOAP library such as Apache Axis2. The library will include tools for generating Java classes from WSDLs. You would use that generated code to make the web service calls.
Based on your first sample I think you use the CXF framework.
This framework provides a task named wsdl2java that allows to generate classes from a WSDL file.
Once your classes are generated you can use them in your code to call the Web Service in an easy way without having to build the SOAP message by hand. It's CXF's job to do this.
I think it helps if you refer few basics of web-services in java
http://www.oracle.com/technetwork/java/index-jsp-137004.html
http://metro.java.net/

How to utilize web service client generated from WSDL?

I'm trying to write a simple web service client to interact with my simple web service which only returns a user id that's passed in. So I created a web service client in eclipse and generated a few files for me; wsCall, wsCallBindingStub, wsCallProxy, wsCallService, wsCallServiceLocator. The stub is the conly class I found that has my web service methods in it, because my ws is simple at this stage?
So I want to invoke the call, what do I need to make the call?
I've seen all the examples online have the try-catch for a remote exception or Axis fault, then the classes are instantiated (including a response class, to deserialize?) and make the ws call via the stub class. Is that all I need to call for my case?
wsCallBindingStub stub = new wsCallBindingStub();
String retString = stub.sayHi(1); // 1: my user id
return retString;
Thank you!
Ahh I figured it out, I was getting an error because my wsdl uses the hostname and I needed to specify the ip.. as for the code needed it was pretty much identicle;
wsCall ws = new wsCallServiceLocator().getWsCallPort();
result = ws.sayHi(x);

Categories