Consume SOAP web service without wsdl using spring framework - java

I have to call a web service located in http://ip:port/ws which has no wsdl.
I can send an HTTP POST using Spring framework's RestTemplate and get answer as raw input from the service. But this is annoying a bit, that's why I am looking for the correct way to consume this web service without WSDL.
Can anybody suggest a 'best practice' way for this task?

There is really no best practice, recreating the WSDL or at least the XML Schema seems like your only option to improve upon your current approach.

If you're really lucky, it'll return some consistent XML that you might be able to throw an XPath parser at to extract the bits you need. You might be able to tease out the XML schema either from the data it returns (look for a namespace declaration at the top of the document somewhere, and see if you can follow the URI it references), or drop the data into an on-line schema generator like this one

I could not find the best solution, and did some workaround. So as we know the SOAP call in HTTP environment is a standard HTTP POST with the soap envelope in HTTP POST body. So I did the same. I stored the xml soap requests in different place just not mess with the code:
public static final String REQ_GET_INFO = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:xyz\">" +
" <soapenv:Header/>" +
" <soapenv:Body>" +
" <urn:export>" +
" <cardholderID>%s</cardholderID>" +
" <bankId>dummy_bank</bankId>" +
" </urn:export>" +
" </soapenv:Body>" +
"</soapenv:Envelope>";
And in service layer I used RestTemplate post call with required headers:
#Value("${service.url}") // The address of SOAP Endpoint
private String wsUrl;
public OperationResponse getCustomerInfo(Card card) {
OperationResponse operationResponse = new OperationResponse(ResultCode.ERROR);
try {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "text/xml");
HttpEntity<String> request = new HttpEntity<>(String.format(Constants.SoapRequest.REQ_GET_INFO,
card.getCardholderId()), headers);
String result = restTemplate.postForObject(wsUrl, request, String.class);
if(!result.contains("<SOAP-ENV:Fault>")) {
// Do SOAP Envelope body parsing here
}
}
catch(Exception e) {
log.error(e.getMessage(), e);
}
return operationResponse;
}
A little bit of dirty job, but it worked for me :)

Related

How to get response in list form using Unirest?

My project is written in the Java programming language using the Spring Boot framework.
I use Unirest library for getting requests to some API and I want to get response in forms, which looks like List<SomeResponse>
Below I write some example of request, which I try to make.
Why do I need a list? Because this data structure is more convenient and used throughout the rest of the huge project.
I tried various options for receiving a response to the request, but I could not get the List <SomeResponse> in any way. At the moment, my efforts have led me only to the fact that I get an array of the objects I need. Of course, we could try to cast the array to list, but here, as it seems to me, we lose in speed.
try {
SomeResponse[] SomeResponses = Unirest.post(url)
.header("Content-Type", "application/json")
.header("Authorization", key)
.body("[\"" + address + "\"]")
.asObject(SomeResponse[].class)
.getBody();
return Result.ok(SomeResponses);
} catch (UnirestException e) {
return Result.error("Error in call API " + url);
}
Also, I have configured the Jackson library, which serializes the JSON format, which that we receive in response to a request, in POJO classes. Perhaps you could tell how to configure the mapper correctly so that it can accept and serialize this response.
Few words about versions of libraries and frameworks. I used Gradle to build and manage dependencies.
org.springframework.boot:spring-boot-starter:2.0.0.RELEASE
com.fasterxml.jackson.core:jackson-databind:2.10.1
com.mashape.unirest:unirest-java:1.4.9
Thanks a lot for your answers!
P.S.
Sorry, this question may have a bad structure, but this is the first time I am writing a problem on this platform, I promise to make my question better in the future.
Replace the SomeResponse[].class in asObject with a GenericType<List<SomeResponse>> object.
try {
List<SomeResponse> someResponses = Unirest.post(url)
.header("Content-Type", "application/json")
.header("Authorization", key)
.body("[\"" + address + "\"]")
.asObject(new GenericType<List<SomeResponse>>() {})
.getBody();
return Result.ok(someResponses);
} catch (UnirestException e) {
return Result.error("Error in call API " + url);
}

Rest api call and POST request (java)

I am pretty new concerning REST api and POST request.
I have the url of a REST api. I need to access to this api by doing an API call in JAVA thanks to a client id and a client secret (I found a way to hash the client secret). However, as I am new I don't know how to do that api call. I did my research during this all day on internet but I found no tutorial, website or anything else about how to do an api call. So please, does anyone know a tutorial or how to do that? (if you also have something about POST request it would be great)
I would be very thankful.
Thank you very much for your kind attention.
Sassir
Here's a basic example snippet using JDK classes only. This might help you understand HTTP-based RESTful services a little better than using a client helper. The order in which you call these methods is crucial. If you have issues, add a comments with your issue and I will help you through it.
URL target = new URL("http://www.google.com");
HttpURLConnectionconn = (HttpURLConnection) target.openConnection();
conn.setRequestMethod("GET");
// used for POST and PUT, usually
// conn.setDoOutput(true);
// OutputStream toWriteTo = conn.getOutputStream();
conn.connect();
int responseCode = conn.getResponseCode();
try
{
InputStream response = conn.getInputStream();
}
catch (IOException e)
{
InputStream error = conn.getErrorStream();
}
You can also use RestTemplate from Spring: https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
Fast and simple solution without any boilerplate code.
Simple example:
RestTemplate rest = new RestTemplate();
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("firstParamater", "parameterValue");
map.add("secondParameter", "differentValue");
rest.postForObject("http://your-rest-api-url", map, String.class);
The Restlet framework also allows you to do such thing thanks to its class ClientResource. In the code below, you build and send a JSON content within the POST request:
ClientResource cr = new ClientResource("http://...");
SONObject jo = new JSONObject();
jo.add("entryOne", "...");
jo.add("entryTow", "...");
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Restlet allows to send any kind of content (JSON, XML, YAML, ...) and can also manage the bean / representation conversion for you using its converter feature (creation of the representation based on a bean - this answer gives you more details: XML & JSON web api : automatic mapping from POJOs?).
You can also note that HTTP provides an header Authorization that allows to provide authentication hints for a request. Several technologies are supported here: basic, oauth, ... This link could help you at this level: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
Using authentication (basic authentication for example) can be done like this:
String username = (...)
String password = (...)
cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, username, password);
(...)
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Hope it helps you,
Thierry

REST/JSON : How to generate sample requests ? How to expose API?

Using java, when I expose some web service with Soap, I have a WSDL which describes all input/output, and if I use this WSDL in my SoapUI client, it will analyze it and generate some sample request for me.
What is the process to do this with Rest/Json. I know about wadl, but SoapUI can't generate sample request from this. I know about third party tools like Swagger suite, but is this the only way ? Do u have to use some external documentation tool to expose your API and show users some sample requests ?
There is no answer yet, so here is one a few years later.
You need to use OpenAPI Specification (let's call the result a "Swagger contract"), which defines a standard, language-agnostic interface to RESTful APIs and just forget about WADL.
This will be the equivalent of a SOAP WSDL, but easier to read , easier to produce, and lighter in constraints.
With Swagger, you can work in "Contract first" (using https://editor.swagger.io/ to design the contract) or in "Code first", where you will use frameworks like Springfox to generate the swagger contract from code + annotations. The last one is much easier imo, and it's just a different way of doing "contract first", it's not like if u were implementing the whole application before designing the contract.
Once you have the "swagger contract" document available on an URL, you can deploy a swagger-ui website to visualize it in an interactive way : it will generate some sample requests and will allow you to execute these requests after customizing them.
try {
url="put your service url";
HttpPost request = new HttpPost(url);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
// Build JSON string
JSONStringer item = new JSONStringer()
.object()
.key("password").value(pass)
.key("username").value(email)
.endObject();
StringEntity entity = new StringEntity(item.toString());
request.setEntity(entity);
// Send request to WCF service
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity entity1 = response.getEntity();
InputStream stream = entity1.getContent();
r = Splash.convertStreamToString(stream);
JSONObject jo = new JSONObject(r);
s= (Integer) jo.get("Flag");
Log.d("json result is:", r);
statusCode = response.getStatusLine().getStatusCode();
} catch (Exception e) {
e.printStackTrace();
Log.d("error", "code"+0);
}
return s;
}

Where does Android RESTful POST go?

I want to first say that I am a newbie to Android and java (to a lesser extent). I have a client-server application, the client is an Android app and the server is running Tomcat. Considering I am new at this I am a little confused about the POST request. The Client has a couple text fields, the user enters information and hits a button that calls on a method that well does a POST task. I can see that the server receives the data from the POST form in the client but my question is where does that information (from the form) go? It is supposed to create a new resource (in this case a Person resource)...Here is the code from the PersonResource class that does the POST.
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
public Person postPerson(MultivaluedMap<String, String> personParams) {
String firstName = personParams.getFirst(FIRST_NAME);
String lastName = personParams.getFirst(LAST_NAME);
String email = personParams.getFirst(EMAIL);
System.out.println ("System storing: " + firstName + " " + lastName + " " + email);
person.setFirstName(firstName);
person.setLastName(lastName);
person.setEmail(email);
System.out.println ("person info: " + person.getFirstName() + " " + person.getLastName() + " " + person.getEmail() + " " + person.getId());
return person;
}
It returns a person resource but ultimately where does that person resource go? I am sorry if I have not provided all required information needed to solve this problem. If more information is needed I will be happy to provide it. I truly appreciate any help given. Thank you.
I am not sure I fully understand the question, but here is an overview that might be helpful:
The client POST sends an HTTP request to the server. The server must have some sort of web service framework (e.g. Jersey or CXF or ...) that processes the request. The JAX-RS annotations on your class (#POST and #Consume), instruct the web service framework to route the request to the postPerson method of your class. It sounds like this much is working, yes?
Your method then constructs a Person object based upon the contents of the form, i.e. the user input. Your method returns this Person to the web service framework.
So what happens to this person? The #Produces annotation you have provided, instructs the web service framework to generate a JSON representation of the person and include this in the body of the HTTP response that is sent back to the client. The response might look something like this:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 259
{"fistName":"Bob", "lastName":"Barker", "email":"bob_bark#priceisright.com"}
Is this what you were looking for?
You can use HttpPost to submit the request and then use gson to convert the response back to object. The HttpPost should be placed under async request (i.e AsyncTask). You can refer
http://www.androidsnippets.com/executing-a-http-post-request-with-httpclient
Async HTTP post android
http://code.google.com/p/google-gson/

How to send a POST request with parameters to an endpoint via JBoss HttpRouter?

I'm working on an ESB project and I need to call a REST service using a POST request. HttpRouter seems to be the right way to do it since it supports both GET and POST methods but I can't find a way to inject parameters inside my call.
How can I do that ?
You can try Apache HTTP library. It's very easy to use and have comprehensive set of class needed to manipulate HTTP request.
Found the answer... It was pretty dumb. All you need to do is to inject parameters inside the Message object and they will be in the body of the request. Here is a sample code created by JBoss and found from a unit test of HttpRouter :
final ConfigTree tree = new ConfigTree("WrappedMessage");
tree.setAttribute("endpointUrl", "http://127.0.0.1:8080/esb-echo");
tree.setAttribute("method", "post");
tree.setAttribute("unwrap", "false");
tree.setAttribute("MappedHeaderList", "SOAPAction, Content-Type, Accept, If-Modified-Since");
HttpRouter router = new HttpRouter(tree);
Message message = MessageFactory.getInstance().getMessage(type);
message.getBody().add("bar");
Message response = router.process(message);
String responseBody = (String)response.getBody().get();
String responseStr = null;
if (deserialize)
responseStr = Encoding.decodeToObject(responseBody).toString();
else
responseStr = responseBody;
return responseStr;

Categories