RESTful services with AXL - rest

I am trying to create a few restful webservices that will add a bit functionality to the company cisco phones. The basic idea is simple, the users get a small client on which they need to enter login and password. When they have done so, their phone/phones are 'registered' to my restful service and they get added functions on their phone. When they log out, they get unregistered. To provide the extra functions (like adjusted caller information etc etc) I need the Cisco AXL API. This is a SOAP based API. I have generated the java classes using the wsdl already. When I make a testclient using the generated classes, all works fine.
But here comes the problem: When I try to run a soap request while my application is deployed on my Tomcat 7 container, it doesn't work anymore.
The problem seems to be the AXLAPIService, which hangs when executing the following piece of code:
#WebEndpoint(name = "AXLPort")
public AXLPort getAXLPort() {
return super.getPort(new QName("http://www.cisco.com/AXLAPIService/", "AXLPort"), AXLPort.class);
}
In other words, i am not getting a port for the soap request and it makes the tomcat crash i f you wait long enough.
I went googling. Somebody on some forum once had a problem because of an out of date stax version. I adjusted the stax version in my POM and tried again, to no help.
I also read somewhere that the underlaying javax.xml.ws.Service actually has an enumeration of ports, and when you do getPort(), you will get the most appropiate port. I then looked up the default port for SOAP and that would be 80, just like the port used for RESTful services. Could it be that the soap service would be wanting port 80, but that it can't have it because it is already in use?
So, to summarize my question:
can it be that my restful services consume the same port that my soap
request would want to use?
if not, what could be the problem then and how should I fix it?
As additional information, this is how the axl wsdl defines the service:
<service name="AXLAPIService">
<port binding="s0:AXLAPIBinding" name="AXLPort">
<soap:address location="https://CCMSERVERNAME:8443/axl/"/>
</port>
I was thinking about changing the soap port myself. Some googling tells me I should do that in the wsdl but I wouldn't really know how. There is post already here but I fail to see how binding another portname could help me out....

As with so many things involving Cisco Telephony and their Administrative XmL (AXL), I found a workaround instead of an actual answer. Since a problem never really leaves my mind, I spent the rest of yesterday trying to find a solution for getting information out of that AXL thing.
Any actual answers to the above questions are still welcome though.
The workaround I found is this: Since SOAP can be seen as a special http POST request, it should be possible to do a SOAP call using a REST framework such as Jersey. You just need some extra code to make it work. I used the 'SoapProvider' from the link and for those who are also wrestling with this, I'll add my code:
public void doSoapRequest() throws SOAPException, JAXBException{
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(SoapProvider.class);
Client c = Client.create(config);
c.addFilter(new LoggingFilter());
c.addFilter(new HTTPBasicAuthFilter("user", "password"));
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPBody body = envelope.getBody();
SOAPElement bodyElement = body.addChildElement(envelope.createName("getCCMVersion", "", "http://www.cisco.com/AXL/API/8.5"));
message.saveChanges();
WebResource service = c.resource("https://youraxlmachine:8443/axl/");
// POST the request
ClientResponse cr = service.type(MediaType.TEXT_XML).header("SOAPAction", "\"https://youraxlmachine:8443/axl/getCCMVersion\"").post(ClientResponse.class, message);
message = cr.getEntity(SOAPMessage.class);
JAXBContext ctx = JAXBContext.newInstance(GetCCMVersionRes.class);
Unmarshaller um = ctx.createUnmarshaller();
GetCCMVersionRes response = (um.unmarshal(message.getSOAPPart().getEnvelope().getBody().extractContentAsDocument(), GetCCMVersionRes.class)).getValue();
System.out.println("HERE COMES THE VERSION!");
System.out.println(response.getReturn().getComponentVersion().getVersion());
}
I have left as many things unchanged as I could, except for the company specific details. This code works for getting the CCM version.
WARNING: Depending on how you perform the request, you might get a different result for the same request. I'll explain:
I have implemented other AXL methods as well, such as getUser. Before I even coding the Jersey soap service, I tried everything with SOAPUI. So I setup the SOAPUI so I could do RESTful requests to the AXL server. Using my restful setup in SOAPUI, I get the same results as I when would do the standard SOAP calls using both SOAPUI and my first implementation of a soapclient in java.
But when I use the jersey client to do the same getUser request, some important fields are missing from the result. I have no clue what could have caused this. For the request getPhone, I dont even get a valid response. So be warned.

Related

SoapCore and Message Header

I have a customer that requires us to use a SOAP service (and yes...I tried to have that changed and no go). The soap message needs to look like this with an AuthHeader in the Header.
I've tried using SoapCore with an IMessageInspector2 and a MessageHeader attribute but no luck
Does anyone have a solution for this? I have to send the WSDL to our customer so they can code against it.

How to call soap web service from camel rest java DEL

I am trying to call soap web service from camel rest, from java DSL. but getting server error with 500 response code.
I will receive call from a rest with json data and i have to make call to a third party soap service also i need to process the soap response and send back the response in json formate.
here is my code
{
String getCustomerDetailsurl="http://<serverip>/webservice/Service.asmx?op=GetClientDetail&bridgeEndpoint=true";
rest("/customers")
.description("Aviva Mobile sales customer service")
.consumes("application/json")
.produces("application/json")
.post().type(ClientRequest.class) // incomming request data
.route()
.from("direct:start")
//.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.process(new CustomerProcessor()).marshal().xstream()
.to(getCustomerDetailsurl);
Error
org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://<serverip>/webservice/Service.asmx?op=GetClientDetail with statusCode: 500
at org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:239) ~[camel-http-2.17.5.jar:2.17.5]
at org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:161) ~[camel-http-2.17.5.jar:2.17.5]
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) ~[camel-core-2.17.5.jar:2.17.5]
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145) ~[camel-core-2.17.5.jar:2.17.5]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77) ~[camel-core-2.17.5.jar:2.17.5]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468) ~[camel-core-2.17.5.jar:2.17.5]
}
You have to look at Server side for what actual error is.
You may use some tool like tcp monitor (tcpMon) to see exactly what you send and what you get back.
Actually, To use SOAP service it is much better to use SOAP client, rather than raw call through http. Take a look at Camel-CXF component. Then create a CXF endpoint and use it uri in your .to({cxfEndpointUri}). CXF will do all SOAP work for you. Maybe you will need to make a little work in its interceptors, like authorization if Server requires it.
P.S. In your code what kind of Exchange.body your CustomerProcessor produces? is it a valid for server SOAP Envelope? does it have all what server requires by its contract (WSDL)?

Create WSDL message from SOAP Response

I have a WSDL that contains a different response then the actual responds with. I want to update the WSDL with the format of the API response but am having trouble. Is there a tool to generate a WSDL response from SOAP XML?
I should mention that they gave me the WSDL as a file, no public WSDL is visible.
The response contains this unknown anonymous xml element, s-gensym3. It should be userid.
If it's a .NET web service you can browse to [serviceurl]?WSDL to get the WSDL.
There's surely service endpoint you communicate with. You shall be able to invoke this endpoint in the browser and add to the end:
?wsdl
i.e. http://service:8123/operationName?wsdl
This will print you entire WSDL. Just make sure you have the same and you're done.

Getting started with Rally REST webservice API

Was after some help on getting started with calling the Rally REST webservice from a .NET MVC webclient.
I've been given the web service info here:
https://rally1.rallydev.com/slm/doc/webservice/
So I can see that I can use a URL to access information from Rally - Similar to:
https://rally1.rallydev.com/slm/webservice/1.39/task?query=((Owner.Name
= owner#blah.com.au) and (State != Completed))&order=Rank&fetch=true&stylesheet=/slm/doc/webservice/browser.xsl
However what I'm not clear on is how to authenticate before making my request?
I'm new to REST web services (have done the SOAP/WSDL awhile back) - so it doesn't seem like with REST you're supposed to add a reference to something to get client classes created? Is this correct? That you just create a HTTPRequest using a URI - and make the call, getting back a HTTPResponse (which I can hopefully do something with).
A lot of examples seem to have specific service/api classes that they're calling methods on or accessing properties - so I'm not sure if that's because they're using SOAP rather than REST - or that they created them themselves.
Maybe I'm looking at the wrong documentation as it seems assumed you know how to be authenticated. Or I'm missing a reference?
I know the question is old, but this might help someone else. You need to pass a Basic Authentication header with your base64-encoded username and password as part of your get() request. I found this information on an Atlassian documentation page and successfully applied it with Rally API 3.0 (should also work with 2.0). So in your get() request, include a header similar to the following:
auth_header = 'Authorization : Basic ' + base64_encode('username:password')

Consuming a RESTful web service using Apache Camel

I am trying to consume a restful Web service using camel.
For that I am configuring dynamic endpoint url as the RESTful url is created at the runtime. Everytime I am checking if the particular endpoint url is registered as a route in my camel context using following method of CamelContext class.
Endpoint hasEndpoint(String uri);
In this case, if the endpoint is not registered then I add a route to my camel context using a custom Route Builder.
I am using camel HTTP component for this. This is working fine for me as of now.
However, I believe performance wise this is not good as everytime I have to check if a route is registered with the camel context and if not then register the same before making the webservice call.
Can some body please tell me if there is a better way to consume RESTful Web services in camel?
I also want to know if the RESTful webservice I am consuming uses OAuth 2.0 protocol, do I need to change anything in my code as I am just consuming it?
Regards, Nilotpal
Thanks for your reply.
I am checking if the route is already exists to make sure I don't end up adding duplicate route(s) to the camel context.
Regarding long lived routes and route dynamics, can u please explain a bit regarding this? How do I implement route dynamics?
It would also be helpful if you could point me to some CXF-RS producer example.. I read the documentation of CXFRS but could not understand it clearly.
Thanks
Nilotpal
Exactly why do you need to check if the route is registred or not before making the call? You should perhaps setup a more long lived route and route dynamic towards resfull resources.
As for Rest with camel, I think the HTTP component does a great job, but there are higher level components to use as well, more designed for REST.
CXFRS and Restlet, producer examples for restlet can be found in the Apache Camel source unit tests, such as this RestletProducerGetTest.java.
As for oAuth 2.0, Camel has some oAuth support built-in, especially for google. Look for the gauth component. There is even a tutorial, however it might not be aligned with your case, it still might give some background so you could solve your issues: http://camel.apache.org/tutorial-oauth.html
CamelContext context = new DefaultCamelContext();
My Aim
I am trying to intercept the incoming request and based on the ip of the incoming request i want to invoke dynamic endpoint of get offers
context.addRoutes(new RouteBuilder(){
public void configure(){
from("jetty:localhost:9000/offers")
.process(new Processor(){
public void process(Exchange exchange) throws Exception {
//getting the request object
HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class);
//Extracting information from the request
String requestIP=req.getRemoteAddr();
/**
* After getting the ip address i do necessay processing
* and then add a property to exchange object.
* Destination ip address is the address to which i want to
* send my request
*/
exchange.setProperty("operatorAddress",destinationIpAddress);
}
})
.to("direct:getOffers")
.end();
}
});
Now i will invoke the getOffers endpoint
so first i will register it
context.addRoutes(new RouteBuilder(){
public void configure(){
from("direct:getOffers")
.toD("jetty:${property.operatorAddress}/api/v2.0/offers?
bridgeEndpoint=true")
.end();
}
});
so we can access the operatorAddress property of exchange object as
${property.operatorAddress}
also when we have dynamic routes then we need to call
.toD() and not .to()