Migrating a CXF client that uses "simple frontend" to JAX-WS - web-services

I have a web service client written with Apache CXF, that uses the simple frontend style. It can dynamically invoke a method on a remote web service, given its location and the interface implemented by the service.
public static void callWsMethod(Class<?> serviceInterface, String address, String methodName,...) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(serviceInterface);
factory.setAddress(address);
Object instance = factory.create();
... /*invoke method "methodName" on instance */
I want to migrate this code to a pure JAX-WS implementation. My code should look something like:
public static void callWsMethod(Class<?> serviceInterface, String address, String methodName,...) {
URL wsdlLocation = new URL(address + "?wsdl");
QName serviceName = new QName( .... , ....); //??? what goes here
Service service = Service.create(wsdlLocation, serviceName);
Object instance = service.getPort(serviceInterface);
... /*invoke method "methodName" on instance */
I suspect that this is possible because the CXF doc cited above says:
In a 'simple' case, very nearly identical things happen in the Simple front end as in JAX-WS.
My first problem is the QName constructor:
QName(java.lang.String namespaceURI, java.lang.String localPart)
how does CXF figure out the right namespaceURI and localPart to invoke the ws?

Do you have a WSDL?
namespaceUri = /wsdl:definitions/#targetNamespace
localPort = /wsdl:definitions/wsdl:service/#name
If you have a WSDL. Why not simply generate the SEI classes using wsimport? You'll see the generated automatically contains the right QName.

Related

How to use web service Soap Client method with Xamarin

I have added my web service Url to my application through the steps of "Add Web Reference" with the name of "SOAPNyd" in Xamarin Studio
Now I need to connect my web Methods, I see my web referenced methods under Web Service folder but can not connect to them and need know how to call , use my methods.
Could anyone show me one example with while loop to write down its all data to the Console please. Thank you.
here is one of my methods which returns all brands that I have at Data Base first value is empty second value is my pasword dont worry about parameters
public string getMarkalarlist(string s, string key) {
getMarkalarlistRequest1 inValue = new getMarkalarlistRequest1();
inValue.s = s;
inValue.key = key;
getMarkalarlistResponse1 retVal = ((WebDBServicesHttpGet)(this)).getMarkalarlist(inValue);
return retVal.#string;
}
a piece of my need
http://www.nullskull.com/a/10476774/consuming-web-services-using-xamarin.aspx

Apply HTTP basic authentication to jax ws (HttpSpiContextHandler) in embedded Jetty

There are some similar questions for earlier versions of Jetty (pre 9) but none that address this specific problem :
Server server = new Server();
System.setProperty("com.sun.net.httpserver.HttpServerProvider",
JettyHttpServerProvider.class.getName());
JettyHttpServer jettyServer = new JettyHttpServer(server, true);
Endpoint endpoint = Endpoint.create(new SOAPService()); // this class to handle all ws requests
endpoint.publish(jettyServer.createContext("/service")); // access by path
server.start()
Simplified code example above to show the only way that I have found to bridge between Jetty and incoming soap requests to my jax-ws service. All settings are in code with no web.xml, this is part of a larger solution that has multiple contexts and connections for different purposes (servlets etc..)
I have tried to add a handler class to the jettyServer.createContext("/service",new handler()) to see if I can perform a header extraction to simulate basic auth but it never gets executed.
My problem is that i cannot find a way to specify, by code against the Jetty server, to use basic authentication. Using the setSecurityHandler method of a ServletContextHandler is easy and works great for other contexts, i just can't figure out how to use this concept for the jax-ws service.
Any help would be much appreciated.
p.s. SSL is already implemented, I just need to add http basic auth.
For anyone else that may of come across the same problem here is the answer that i stumbled on eventually.
final HttpContext httpContext = jettyServer.createContext("/service");
com.sun.net.httpserver.BasicAuthenticator a = new com.sun.net.httpserver.BasicAuthenticator("") {
public boolean checkCredentials (String username, String pw)
{
return username.equals("username") && pw.equals("password");
}
};
httpContext.setAuthenticator(a);
endpoint.publish(httpContext);//access by path
You can expand the checkCredentials for something a bit more sophisticated of course, but this shows the basic working method.

How to Ignore wsit-client.xml when calling web service if exists

The application I am working on calls many webservice. Just recently I have intergrated another web service that requires wsit-client.xml for Soap authentication.
That is working now but all the other SOAP services have stopped working.
Whenever any of them is being called, I see messages like
INFO: WSP5018: Loaded WSIT configuration from file: jar:file:/opt/atlasconf/atlas.20130307/bin/soap-sdd-1.0.0.jar!/META-INF/wsit-client.xml.
I suspect this is what is causing the Service calls to fail.
How can I cause the wsit-client.xml to be ignored for certain soap service calls?
Thanks
Fixed it by Using a Container and a Loader to configure a dynamic location for the wsit-client.xml. This way it is not automatically loaded. To do that, I first implemented a Container for the app as shown below
public class WsitClientConfigurationContainer extends Container {
private static final String CLIENT_CONFIG = "custom/location/wsit-client.xml";
private final ResourceLoader loader = new ResourceLoader() {
public URL getResource(String resource) {
return getClass().getClassLoader().getResource(CLIENT_CONFIG);
}
};
#Override
public <T> T getSPI(Class<T> spiType) {
if (spiType == ResourceLoader.class) {
return spiType.cast(loader);
}
return null;
}
}
Then to use it in the Code I do this
URL WSDL_LOCATION = this.getClass().getResource("/path/to/wsdl/mysvc.wsdl");
WSService.InitParams initParams = new WSService.InitParams();
initParams.setContainer(new WsitClientConfigurationContainer());
secGtwService = WSService.create(WSDL_LOCATION, SECGTWSERVICE_QNAME, initParams);
And it works like magic

Spring Web - Restful Webservice - pass/receive ArrayList as an argument/parameter in client/server side

I have created a sample application to get full idea of Spring MVC with REST Webservice. I have created an application which host webservice and a client which calls to this webservice and fetch the relevant data. I am able to pass the arguments from client side like String, and able to receive the data as List or single object, and till here it goes smooth..
Now I want to pass the List as an argument from client side, and also want to implement on webservice side to get the List which is passed from client application. Can anyone helpout with this scenario?
Please find code snippet of my working version.
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("appContext.xml", Client.class);
RestTemplate restTemplate = applicationContext.getBean("restTemplate", RestTemplate.class);
String url;
// retrieve a list of customers
url = "http://localhost:8080/restful-ws/app/testlist.xml";
List<CustomerBean> custList = (List) restTemplate.getForObject(url, List.class);
for (CustomerBean cust : custList) {
System.out.println(">> cust :"+ cust.toString());}
Web Service side implementation.
#RequestMapping(method=RequestMethod.GET, value="/testlist")
public ModelAndView showCustomers() {
ModelAndView mv = new ModelAndView("customerListKey");
List<Customer> custs = new ArrayList<Customer>();
for (Customer customer:customers.values()) {
custs.add(customer);
}
mv.addObject("allCustomers", custs);
return mv;
}
also i have related files, but if will put all code snippets, it will become too much. Mainly my query is how can I pass List from client side and how can i get it from receiver/server side?, in both side i am using spring only
Thanks in advance for your time and help.
-Ronak.
Use an array of CustomerBean
CustomerBean[] custList = restTemplate.getForObject(url, CustomerBean[].class);
The conversion from array to list is left as an exercise for the interested reader...

JAX-WS web service with Source return type on Websphere

I am migrating an old JAX-WS 2.1 web service from JBoss 4 to Websphere 7. Most of the #WebMethod components all look like this:
#WebMethod
public Source someMethod(){
Source source = null;
try{
source = ServiceActions.someMethodWorker();
}
catch( Throwable throwable ){
source = ServiceActions.handleThrowable("Error occured in method someMethod", throwable );
}
return source;
}
ServiceActions.someMethodWorker() usually goes off and fetches that data populates a JAXB structure, marshalls into XML and returns a StreamSource of the XML like this:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
JAXBContext jc = JAXBContext.newInstance();
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(someJaxBObjectHierarchy, byteArrayOutputStream);
return new StreamSource(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
This web service runs just fine on JBoss 4 (with the Jax-WS and JaxB libraries) and GlassFish 3.1, but Websphere 7 keeps giving me the following error any time I use a client against the web service:
javax.xml.ws.soap.SOAPFaultException: javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class javax.xml.transform.stream.StreamSource nor any of its super class is known to this context.]
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
At first look this seems to be the JAXB type binding problem; however, I've added #XmlSeeAlso(StreamSource.class) everywhere, and I still get the error.
Would someone know why this is failing on WebSphere 7?
Thanks!
Edit/Solution: The solution is to use byte[] return type instead of Source
GlassFish and JBoss were doing something extra compared to the JAX-WS specification which led me to believe that Source return type was OK.
Instead of my methods returning new StreamSource(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())) they now just return byteArrayOutputStream.toByteArray()
javax.xml.transform.Source is not a valid return type for a normal JAX-WS service endpoint interface (SEI). If you want to do that (and be compliant with JAX-WS) you need to use a service that is implemented as a javax.xml.ws.Provider (see the corresponding docs). If JBoss or GlassFish support Source as a parameter or return type in a normal SEI, then that's a proprietary extension.