Apache CXF - Providing SEI to Customer - java

For customers to create apache cxf client of your web service, if they use JaxWsProxyFactoryBean, they need the endpoint address and the SEI code. About providing endpoint address there is no problem, but how you provide the SEI ? You just export the interface within a jar and give the jar to the customer ? Each time you change the SEI, you must contact with all customers and give the jar again ?
I mean the IDataService interface in below example:
public static void main(String[] args) throws SomeException {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(IDataService.class);
factory.setAddress("http://localhost:8080/WSTest/services/dataService");
IDataService client = (IDataService) factory.create();
}

Ideally you should just be giving them the WSDL of the service - WSDL should the contract here using which they can generate their own set of templates using whatever tool is available to them - wsdl2java etc.
If the client is an internal to your company, then yes, you can as well create a thin project with just the interfaces, types, messages, package it as a jar and provide the jar via some internal repository, assuming that your interface does not too often and even if it changes, that it is published afresh to the internal repository.

Related

wsdl2java and axis2 webservice setup and testing

I am very new to the building of web-services, so please forgive my ignorance.
I have been given some an .wsdl files with some .xsd files that it imports.
I am told that a web-service can be created from the .wsdl file by using wsdl2java from the apache axis2 project.
The web-service I am trying to build is expecting to have data pushed to it and I would like to test it that I have the process right for data to be pushed to a web-service that I created.
The basis for my actions have been from here, but not too sure how much of it is applicable.
I am on a MacOSX but also have access to an ubuntu system too.
the steps I have taken so far are:
cd /directory/of/wsdl/file
wsdl2java.sh -uri tmp.wsdl -d adb -s
This creates a build.xml file and src directory
I then try and run
ant
or
ant jar.client
After this I am not too sure what to do, in order to get the web-server running so that I could test it...any suggestions would be greatly appreciated.
Thanks in advance.
In SOAP web service:-
The basic concept in web service is that it has consumer and producer.
A consumer is one which consumes a web service and a producer is one which produces a web service. A producer publish its service so that consumer can consume it. It basically publishes a wsdl file so that you can create a client code or jar out of it and can directly call it from your code. You can use soap UI to call the web service directly as well. If you are looking for generating producer code from wsdl as well it will not be good enough since it will not provide business logic to you and you need to implement it by yourself. This is not a recommended approach. Generally first java implementation is written and based on it a wsdl is created from which client jars are created for the clients to use the web service in their code. For directly testing the producer soapui is used.
If you want to create producer it is a straight forward process. Need to create a dynamic project in eclipse-->create a class-->use #WebService(serviceName="xyz") on class and similarly on method level define #WebMethod. Deploy it as run on server and you are done with your Hello World Web service producer.
For creating the client:-
Lets take an example of a published wsdl on the net as :-
http://www.webservicex.net/geoipservice.asmx?WSDL
First you need to create the client jar or java classes as :-
wsimport -keep -s C:\wsdl http://www.webservicex.net/geoipservice.asmx?WSDL
Look at the documentation or look at the service name in the wsdl.
It will be GeoIPService.
Now in your class call the webservice method as:-
package com.soap.client;
import net.webservicex.GeoIP;
import net.webservicex.GeoIPService;
import net.webservicex.GeoIPServiceSoap;
public class SoapWebServiceClient {
public static void main(String[] args) {
GeoIPService ipService = new GeoIPService();
GeoIPServiceSoap gp = ipService.getGeoIPServiceSoap();
GeoIP ip = gp.getGeoIP("117.198.208.1"); //google.com
System.out.println(ip.getCountryName());
}
}
Now similarly for local wsdl you can create classes and jars by
using axis2 or simply wsimport
Put your wsdl and schemas in a folder as shown below:-
C:\wsdl>wsimport -keep -s C:\wsdl C:\wsdl
C:\wsdl>wsimport -clientjar client.jar C:\wsdl
It will create a client for you. Look at the service name and similarly can test the deployed service from java code as shown above.
For testing using soapui you use need to download it and create a new soap project. Give any name and browse to your local drive where all the schema and wsdl is present. It will create all the requests for your. You need to fill in the values in the request parameters ("?") and run the service. If everything went well it will display a result.
Note:-
wsimport is a command line tool for the JAX-WS reference implementation. The JAX-WS RI uses JAXB for data-binding.
Axis2 merely implements the JAX-WS API to some extent, so the Java artifacts generated can be quite different compared to those generated by the JAX-WS RI. Also Axis2 doesn't use JAXB but instead offers the choice of ADB (default), Apache XmlBeans, or JiBX for data-binding. The most popularly used are either xmlbeans or JAXB.
You lookup the wsdl file from publishing URL and reverse engineer the webservice to generate the types so use wsimport
wsimport -d . -p servicesource -keep tmp.wsdl

Communicating to a SOAP webservice with constantly changing targetNamespace

So there is a SOAP webservice. The targetNamespace in the WSDL dynamically changes based on customer's configurable string. Think of it like
targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com"
I have two questions:
My basic research tells me that this is a pretty weird(bad?) practice for developing webservices. Thoughts ?
How does one write a client for such a webservice ? I have tested using jax-ws stub and it isn't compatible when targetNamespace changes. Any other suggestions ? I have been trying to understand dynamic client generation based on wsdl. Would prefer a nicer path though if one exists
Update:
I am only the client. Service is provided by someone else.
Same customer has multiple environments (eg test,production) where the service is hosted under different targetNamespaces
If the SOAPUI call works even if the targetNamespace has change, you could use a lightweight HTTP library called HTTPCLIENT.
With this library you don't need to generate client, since you are sending the SOAP envelope as a string, the way you would do via SOAPUI.
The downside is to work with Strings.
In theory, it is feasible to create such a Web Service client.
Steps:
Create Java artifacts based on the WSDL using wsimport.exe of JDK (see: http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example as a reference)
For the purposes of the code displayed below, I have used the Calculator WSDL provided by Microsoft
Create a "Dynamic Web Project" via Eclipse J2EE
Copy the Java artifacts created in step #1, under src folder of the project created in step #2.
Create a new Class containing you main method. Normally you would have something similar to:
String wsdlLocation = "127.0.0.1:8088";//Normally you should retrieve that value dynamically
Url url = new URL(wsdlLocation + "?wsdl");// ?wsdl is actually needed
String namespaceURI = "http://Example.org";//Normally you should retrieve that value dynamically
String localPart = "CalculatorService";// as specified in WSDL file (see name attribute of service tag)
QName qname = new QName(namespaceURI, localPart);
CalculatorService service = new CalculatorService(url,qname);
ICalculator iCalculator = service.getICalculator();
int response = iCalculator.add(1, 2);
System.out.println(response);
Now for the tricky part:
If you have followed the example with the aforementioned WSDL, you should now have several Annotated Classes having hard-coded namespace (e.g. ICalculator is annotated with:
#WebResult(name = "result", targetNamespace = "..."))//where ... is similar to http ://example .org
Using Java reflection modify all the hard-coded values at runtime (see an example here: https://stackoverflow.com/a/14276270/2625635 on how to modify Annotations)
The aforementioned solution should do the trick.
Most client frameworks allow you to create an interface for calling your client (i.e. they create a contract interface). They also provide an implementation for that interface and it is the implementation that has specific annotations or extends "SOAP aware" classes, while the interface is clean of such details.
From what you posted I assume the clients have the same interface, it's just the implementation namespace that's different? If yes, then write your application to use the interface then build a jar for each environment's implementation. When you deploy on test servers deploy with the test jar, while on production deploy with the production jar (i.e. pick a different implementation for the same contract depending on the environment).
Even if the framework you use doesn't create an interface for you, you can create one yourself and hide the various implementations behind an adapter of some sort.
You can also do something like edubriguenti suggested but I wouldn't go as far as working with strings. Work with SAAJ instead.

CXF Webservice client breaks when providing wsdl

I've created a webservice client using cxf-codegen maven plugin and then instantiate the service like this:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setEndpointName(SERVICE_NAME);
factory.setAddress("some address");
factory.setServiceClass(Service.class);
this.port = (Service) factory.create();
It all works fine and I can call the webservice. But I have a problem running this on Weblogic(XmlSchemaException: Top-level attributes may not have a 'use') and as a possible solution I'm trying to provide the WSDL file so that it's not regenerated.
But when I add the wsdl:
factory.setWsdlLocation("service.wsdl");
I get this exception:
org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for port {namespace}Service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:179)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:428)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:548)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:265)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:214)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:101)
at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:90)
at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:155)
at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:156)
I cannot modify the wsdl and I'd like to know how is it possible, that the service construction fails if I provide the wsdl the service was generated from.
I use CXF 2.6.11
You may need a factory.setServiceName(...) call in there as well to match the WSDL.

Web Service Auto Generated Files

When I create a new Web service using RSA 7.5 IDE and Web Sphere 7.0 server from a Web Application, then I can see a few auto-generated files created by this process, namely:
1) For the service, a SEI file is created
2) For the models, ser, deser and helper files are created.
But I cant understand what are the use of all these SEI, ser, deser and helper files.
Any valid explanation on this will be much appreciated.
BOUNTY EDIT:
Bounty-Edit:
Since I did not get any response I would like to ask this question again - offering a bounty to encourage an in-depth answer. I would love to know how and when are these files used internally?
Regards,
Service Endpoint Interface (SEI):
SEI is the Java interface corresponding to the Web service port type
being implemented. It is defined by the JAX-RPC, which specifies the
language mapping from WSDL 1.1 to Java. Ref
Or
A service endpoint interface (SEI) is a Java interface that
declares the methods that a client can invoke on the service. Ref
These ser,dser,helper are helpers to convert an XML document into a java object and vice versa (WebServices). Ref
Files generated in the server project: (WebSphere Application Server 6.1 Ref)
According to the settings made during the run of the wizard, the following files in the WeatherJavaBeanWeb project have been created:
Service endpoint interface (SEI): itso.bean.WeatherJavaBean_SEI.java is the interface defining the methods exposed in the Web service.
WSDL file: /WebContent/WEB-INF/wsdl/WeatherJavaBean.wsdl describes the Web service.
Deployment descriptor: webservices.xml, ibm-webservices-ext.xml and ibm-webservices-bnd.xml. These files describe the Web service according to the Web services for J2EE style (JSR 109). The JAX-RPC mapping is described in the WeatherJavaBean_mapping.xml file.
Data mapping files: The helper beans in the itso.objects package perform the data conversion from XML to Java objects and back.
A servlet is defined in the Web deployment descriptor to invoke the JavaBean.
Hope this information help you.
Those files are related to the WebSphere mapping between Java, WSDL, and XML. They are automatically generated, and should not need to be edited. You should pretend they are not there (except if they are not there you may have trouble deploying...).
SEI - Service Endpoint Interface
ser - Serialize
deser - Deserialize
helper - ?
Here are some psuedo-helpful links, that may provide some more insight into your question:
IBM Technotes
WebSphere v6.1 Handbook (check Chapter 15 -> Creating a Web Service --> Generated Files)
All these files are basically generated for webservice.
A web service ia basically a port between 2 running applications independant of the framework or language.
Leta say if you are using java from one side of web service then for complete compilation the java end would need some class files that have those methids which you wish to call on the service.
For this a stub is generated. This stub is basically an interface(SEI).
Also websphere needs additional files for implementing the webservices functionality, thus tge helper files.
This is basically the summary of it.

Connecting to SFDC's test instance using Partner WSDL

I created Java Proxies from partner wsdl fetched from https://login.salesforce.com/
How can I use the same proxies to connect to an SFDC account in https://test.salesforce.com/
It'll depend on the specific client toolkit you're using, but you should be able to set the destination Url before calling login(). For Axis 1.x, you'd do
SoapBindingStub binding = (SoapBindingStub) new SforceServiceLocator().getSoap();
binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY,
"https://test.salesforce.com/services/Soap/u/20.0");

Categories

Resources