Java Rest API client - GET method - Error 415 - java

I am new to writing Java client for Restful API using Apache CXF.
On running below code I am getting error 415 returned which when I looked online shows as "unsupported media type". In order to fix it I changed the code to "target.request(MediaType.APPLICATION_XML)" from original target.request(). However this didn't fix the code.
What is the best way to debug this issue?
Thanks a lot in advance for your time.
Update: After discussion with the Rest API developer I came to know that I need to add a header "("Content-Type", "application/x-www-form-urlencoded");". but I am not sure how to add a header. Does anyone know how to add this header here?
package com.blackhawk.ivr.restAPI.client;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class BlissRestAPI {
public static final String BLISS_SERVICRE_URL = "http://x.x.x.x:9090/services";
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(BLISS_SERVICRE_URL);
target = target.path("/cardmanagementservices/v3/card/status").queryParam("ani", "xxxxxxxxxx").queryParam("card.expiration", "xxxxxx").queryParam("card.number", "xxxxxxxxxxxxxxxx").queryParam("channel.id", "xyz");
Invocation.Builder builder = target.request(MediaType.APPLICATION_XML);
Response response = builder.get();
System.out.println(response.getStatus());
response.close();
client.close();
}
}

First you can change the media type as given below.
Client: MediaType.APPLICATION_XML
Rest: MediaType.APPLICATION_JSON
JAX-WS are Java standard to build web service. So you have used it here, As my knowledge it is easy to use axis 2 to this kind of web services and clients since there are more implementations of JAX-WS. So i will give you a solution using apache axis technology.
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.rpc.ParameterMode;
public class axisClient {
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:8090/archive_name/service_name.jws";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName( "service_method_name" );
call.addParameter("parameter_name", XMLType.XSD_STRING, ParameterMode.IN );
call.setReturnType( XMLType.XSD_STRING );
call.setProperty(Call.CHARACTER_SET_ENCODING, "UTF-8");
String jsonString = (String) call.invoke( new Object [] { "parameter_value"});
System.out.println("Got result : " + jsonString);
}
}

I got it working by using below code (got 200 status returned)
WebClient client = WebClient.create(BLISS_SERVICRE_URL);
client.path("/cardmanagementservices/v3/card/status").query("ani", "xxxxxxxxxx").query("card.expiration", "xxxxxx").query("card.number", "xxxxxxxxxxxxxx").query("channel.id", "xxxxx");
client.type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_XML);
client.header("Content-Type","application/x-www-form-urlencoded");
Response response = client.get();
System.out.println(response.getStatus());

Related

How to add HTTP proxy to JAX-WS?

I have a WSDL file which I've turned into Java code by using WSDL2Java inside SoapUI, it works fine, but now I need to add my company's proxy to it, so every SOAP http request would go through it (but not other http requests).
I've looked through multiple threads concerning the same issue and found these options:
system wide proxy by adding
System.getProperties().put("proxySet", "true");
System.getProperties().put("https.proxyHost", "10.10.10.10");
System.getProperties().put("https.proxyPort", "8080");
which doesn't work for me, since it affect the whole jvm.
adding the following code
HelloService hello = new HelloService();
HelloPortType helloPort = cliente.getHelloPort();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(helloPort);
HTTPConduit http = (HTTPConduit) client.getConduit();
http.getClient().setProxyServer("proxy");
http.getClient().setProxyServerPort(8080);
http.getProxyAuthorization().setUserName("user proxy");
http.getProxyAuthorization().setPassword("password proxy");
which I don't get how to use. My generated code doesn't have any traces of org.apache.cxf, only javax.xml.ws.
Adding this to my port configuration:
((BindingProvider) port).getRequestContext().put("http.proxyHost", "proxy#example.com");
((BindingProvider) port).getRequestContext().put("http.proxyPort", "80");
Here I use a random non-existing proxy and expect to get an error of any sort(timeout, invalid proxy, etc.), but instead it goes through without any errors.
Here is an example without using 3rd party libraries.
https://github.com/schuch/jaxws-proxy-example/blob/master/jaxws-client-with-proxy/src/main/java/ch/schu/example/helloworld/Client.java
package ch.schu.example.helloworld;
import java.net.ProxySelector;
import ch.schu.example.hello.HelloImpl;
import ch.schu.example.hello.HelloImplService;
public class Client {
public static void main(String[] args) {
ProxySelector.setDefault(new MyProxySelector());
HelloImplService service = new HelloImplService();
HelloImpl hello = service.getHelloImplPort();
System.out.println(hello.sayHello("Howard Wollowitz"));
}
}
https://github.com/schuch/jaxws-proxy-example/blob/master/jaxws-client-with-proxy/src/main/java/ch/schu/example/helloworld/MyProxySelector.java
package ch.schu.example.helloworld;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.*;
import java.util.*;
public class MyProxySelector extends ProxySelector {
#Override
public List<Proxy> select(URI uri)
{
System.out.println("select for " + uri.toString());
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 9999));
ArrayList<Proxy> list = new ArrayList<Proxy>();
list.add(proxy);
return list;
}
#Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
System.err.println("Connection to " + uri + " failed.");
}
}

How to set source IP to http request?

I need to set source IP address (for something like IP Spoofing) before sending out an http request. Class used for setting up http connection is HTTPURLConnection. I found below link on stackoverflow which is really useful.
Registering and using a custom java.net.URL protocol
As in the post, I have already created 3 classes extending URLConnection , URLStreamHandler and implementing URLStreamHandlerFactory. This looks to be working fine; however I am getting exception which I think is because I have not implemented getInputStream for URLConnection as was mentioned in above post.
I have couple of questions
1> I am extending custom URLConnection class from HTTPURLConnection, so what's the need of implementing getInputStream as anyway it's a virtual method
2> If I have to do it, can someone provide sample implementation of this method?
JMeter already provides the IP Spoofing feature.
In Http Request Defaults, select (in version 3.0 of JMeter) advanced tab :
See http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request_parms1:
Source address field
[Only for HTTP Request with HTTPClient implementation]
This property is used to enable IP Spoofing. It overrides the default local IP address for this sample. The JMeter host must have multiple IP addresses (i.e. IP aliases, network interfaces, devices). The value can be a host name, IP address, or a network interface device such as "eth0" or "lo" or "wlan0".
If the property httpclient.localaddress is defined, that is used for all HttpClient requests.
Based on UBIK LOAD PACK's answer. Here is the same code using Aapche http client 3.x. (The variable for setting source IP is args[1])
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.protocol.Protocol;
public class HC3Test {
public static void main(String[] args) throws Exception {
String url = args[0];
java.net.URL uri = new java.net.URL(url);
HostConfiguration hc = new HostConfiguration();
hc.setHost(uri.getHost(), uri.getPort(), Protocol.getProtocol(uri.getProtocol()));
hc.setLocalAddress(java.net.InetAddress.getByName(args[1]));//for pseudo 'ip spoofing'
HttpClient client = new HttpClient(new SimpleHttpConnectionManager());
client.setHostConfiguration(hc);
GetMethod method = new GetMethod(url);
client.executeMethod(method);
method.releaseConnection();
}
}
Sample code for http client 4.x:
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnRoutePNames;
public class HC4Test {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpClient = new DefaultHttpClient();
org.apache.http.params.HttpParams params = httpClient.getParams();
params.setParameter(ConnRoutePNames.LOCAL_ADDRESS,
java.net.InetAddress.getByName(args[1]));//for pseudo 'ip spoofing'
httpClient.execute(new HttpGet(args[0]));
}
}
To accomplish to have a different source address via an http request you could use a local proxy.
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
public class Huhu {
public static void main(String[] args) throws IOException {
URL url = new URL("http://google.com");
Proxy proxy = new Proxy(Proxy.Type.DIRECT,
new InetSocketAddress(
InetAddress.getByAddress(
new byte[]{your, ip, interface, here}), yourTcpPortHere));
URLConnection conn = url.openConnection(proxy);
}
}
You do not have to override anything this way.

How to call put method in REST assured

I have a put method that accepts inputstream. I want to call this method using rest assured in JUnit.
This is what I used:
with().body(inpustream).put("/service/1"); // i got error 404 forbidden.
POST will return status code 201 and PUT will return 200, and POST will create a new resource but, PUT will update the existing resource. This means we will have to mention which resource we wish to update in the URI itself like below.
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import java.util.HashMap;
import java.util.Map;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.hamcrest.Matchers.*;
public class PUTMethod {
public static Map<String, String> map = new HashMap<String, String>();
#BeforeTest
public void putdata(){
map.put("userId", "2");
map.put("id", "19");
map.put("title", "this is projectdebug.com");
map.put("body", "i am testing REST api with REST-Assured and sending a PUT request.");
RestAssured.baseURI = "http://jsonplaceholder.typicode.com";
RestAssured.basePath = "/posts/";
}
#Test
public void testPUT(){
given()
.contentType("application/json")
.body(map)
.when()
.put("/100")
.then()
.statusCode(200)
.and()
.body("title", equalTo("this is projectdebug.com"));
}
}
Visit http://www.projectdebug.com/send-put-request-using-rest-assured/
for more information.
Actually, you are doing well but sending multipart through PUT is unsecured and is quite random (https://jira.spring.io/browse/SPR-9079). Amend your spring-security.xml to add a filter or use POST method in this case.
You can also try your code by calling another PUT webservice with no stream.
(And what is the error code ? 404 or 403 ?)
A similar problem solved by using MultipartFilter : Spring 3.0 FileUpload only with POST?
Have a look at the following example, where it explains how to use PUT request using Rest Assured:
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static com.jayway.restassured.RestAssured.*;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
public class GetStatusCodeTest {
#BeforeClass
public void setBaseUri () {
RestAssured.baseURI = "https://localhost:3000";
}
#Test
public void updateUsingPut () {
Posts post = new Posts();
post.setId ("3");
post.setTitle ("Hello Bhutan");
post.setAuthor ("StaffWriter");
given().body (post)
.when ()
.contentType (ContentType.JSON)
.put ("/posts/3");
}
}
For detailed explanation, you may check out the following link:
https://restservicestesting.blogspot.in/2016/10/automating-put-request-using-rest.html

Java endpoint - perl consumer web service

I've problem with calling java endpoint (code below) from perl client (activePerl 5.16).
Those code snippets are from book Java Web Services Up And Running
package ch01.ts;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
#WebService
#SOAPBinding(style=Style.RPC)
public interface TimeServer {
#WebMethod
String getTimeAsString();
#WebMethod
long getTimeAsElapsed();
}
package ch01.ts;
import java.util.Date;
import javax.jws.WebService;
#WebService(endpointInterface="ch01.ts.TimeServer")
public class TimeServerImpl implements TimeServer {
public String getTimeAsString() {
return new Date().toString();
}
public long getTimeAsElapsed() {
return new Date().getTime();
}
}
package ch01.ts;
import javax.xml.ws.Endpoint;
public class TimeServerPublisher {
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:9876/ts", new TimeServerImpl());
}
}
And the perl consumer:
use SOAP::Lite;
my $url = 'http://127.0.0.1:9876/ts?wsdl';
my $service = SOAP::Lite->service($url);
print "\nCurrent time is: ",$service->getTimeAsString();
print "\nElapsed miliseconds from the epoch: ", $service->getTimeAsElapsed();
When I'm calling the web service I'm having this stack trace:
maj 04, 2013 10:21:40 AM com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit handle
SEVERE: Couldn't create SOAP message. Expecting Envelope in namespace http://schemas.xmlsoap.org/soap/envelope/, but got http://schemas.xmlsoap.org/wsdl/soap/
com.sun.xml.internal.ws.protocol.soap.VersionMismatchException: Couldn't create SOAP message. Expecting Envelope in namespace http://schemas.xmlsoap.org/soap/envelope/, but got http://schemas.xmlsoap.org/wsdl/soap/
at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(Unknown Source)
I think that the soap version is the problem, above example is from 1.1, when I've change the client code to
my $service = SOAP::Lite->service($url)->soapversion('1.2');
then different error is throw
com.sun.xml.internal.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/soap+xml; charset=utf-8 Supported ones are: [text/xml]
I need help with either dealing with envelope problem or content-type. I will be grateful for any directions, code and anything else that could help.
I am not quite sure of Perl->Soap API, But for first case where client version is 1.1 may be you need to mention namespace also somewhere.
May be like
server->setNamespace() //or
SOAP::Lite->service($url,"<namespace>"); //please search for perl web service client examples
And for second case(1.2) service is expecting text and your api sends soap encoding or something.
Refer http://www.herongyang.com/Web-Services/Perl-SOAP-1-2-Unsupported-Media-Type-application-soap.html
This may be helpful
my $client = SOAP::Lite->new()
->soapversion('1.2')
->envprefix('soap12')
->default_ns('http://xmlme.com/WebServices')
->on_action( sub {join '/', #_} )
->readable(true)
->proxy('http://www.xmlme.com/WSShakespeare.asmx');
and
http://www.herongyang.com/Web-Services/Perl-SOAP-1-2-Request-Differences-SOAP-1-1-and-1-2.html
Hope it helps

Play Framework: How can I read a png image using the WS client?

Hi I'd like to read a PNG from a web service and then respond back to the client with the PNG. (think something like an image proxy). I am using Java and the Play Framework 2.0 with the WS class.
Currently I have:
public static Result getimage(){
WSRequestHolder requestHolder = WS.url("http://someimageserver/myimage.png");
Promise<WS.Response> getImageResult = requestHolder.get();
//How do I create an play.mvc.Result from this so I can sent it back to the callee?
}
Any help is much appreciated.
In Play 2.0.4 you can't do that in Java. First there is no method for binaries in the API: http://www.playframework.org/documentation/api/2.0.4/java/play/libs/WS.Response.html . I tried the method WS.Response.getBody(), but the bytes weren't correct.
But the Scala API supports binary files in Play 2.0.4:
package controllers
import play.api._
import libs.ws.WS
import play.api.mvc._
object Application extends Controller {
def getImage = Action {
Async {
WS.url("http://someimageserver/myimage.png").get().map { r =>
Ok(r.getAHCResponse.getResponseBodyAsBytes).as("image/png")
}
}
}
}
From Play 2.1 on there is support for binaries in Java: https://github.com/playframework/Play20/blob/master/framework/src/play-java/src/main/java/play/libs/WS.java#L565
Thanks, looks like I'll have to be patient :) . I found a workaround though (using ning directly).
//imports
import java.util.concurrent.Future;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
import com.ning.http.client.Response;
//request
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
BoundRequestBuilder prepareGet = asyncHttpClient.prepareGet(url);
Future<Response> fResponse = prepareGet.execute();
Response r = fResponse.get();
InputStream responseBodyAsStream = r.getResponseBodyAsStream();
return ok(responseBodyAsStream).as('image/png');

Categories