how can i get 'jsessionid' using jersey client? - java

I'm using jersey-client 1.19.4 to test my web application.
If I test with postman, I can find the cookie "JSESSIONID" after 'send' action. And I can find 'jsessionid=...' in ClientResponse.toString(), But ClientResponse.getCookies() returns nothing.
WebResource webResource = client.resource(someUrl);
FormDataMultiPart formData = new FormDataMultiPart();
formData.bodyPart(new FormDataBodyPart("userId", userId));
formData.bodyPart(new FormDataBodyPart("uPasswd", uPasswd));
ClientResponse response = webResource.accept("*/*").type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, formData);
System.out.println("response: " + response.toString()); // 'jsessionid' found here
List<NewCookie> cookies = response.getCookies();
System.out.println("# of cookies: " + cookies.size()); // prints "# of cookies: 0"
How can I get "JSESSIONID" from ClientResponse?

JSESSIONID can be set in few different ways. As per
JSR-000315 Java Servlet 3.0 Final Release, chapter 7.1 Session Tracking Mechanisms, following can be used:
Cookies
SSL Sessions
URL Rewriting
In your case it appears that URL Rewriting is being used. The two most common reasons being:
The server is configured not to issue cookies
Your client doesn't support cookies
Since you get the cookie while using Postman it most likely means that your Jersey Client doesn't handle cookies. One way to integrate it with Apache HttpClient using jersey-apache-client as per this answer.

From the mailing list:
http://jersey.576304.n2.nabble.com/Session-Handling-not-working-with-Jersey-Client-td4519663.html
The Jersey client by default uses HttpURLConnection that does not
support cookie management (and thus sessions).
You need to switch to using the Apache HTTP client support.
Then set the following property to true: PROPERTY_HANDLE_COOKIES
DefaultApacheHttpClientConfig config = new
DefaultApacheHttpClientConfig(); config
.setProperty("com.sun.jersey.impl.client.httpclient.handleCookies",
true);
ApacheHttpClient c = ApacheHttpClient.create(config);
Plus you can also use authorization with the Apache HTTP client
integration.
DefaultApacheHttpClientConfig config = new DefaultApacheHttpClientConfig();
config.getState().setCredentials(null, null, -1, "foo", "bar");
ApacheHttpClient c = ApacheHttpClient.create(config);
WebResource r = c.resource("http://host/base");
String s = r.get(String.class);
s = r.post(String.class, s);

Related

JIRA REST API - 415 Unsupported Media Type error in ClientResponse

I am trying to send a POST request via a WebResource instance using a Jersey Client. But no matter how i specify the request headers or types, it will give me a 415 Unsupported Media Type error. Below is my code
String SERVICE_URL = "http://hostIpAddress:8080/JiraUpdate/rest/createin/jira/createticket?"; // hostIpaddress is our server ip
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
System.out.println("SERVICE_URL=" + SERVICE_URL);
WebResource webResource = client.resource(UriBuilder.fromUri(SERVICE_URL).build());
String input = "{\"fields\":{\"project\":{\"key\":\"Invoicing\"},\"summary\":\"REST Test\",\"description\": \"Creating of an issue using project keys and issue type names using the REST API\",\"issuetype\":{\"name\":\"Bug\"}}}";
ClientResponse response = webResource.header("Content-Type", "application/json;charset=UTF-8")
.type(MediaType.TEXT_PLAIN_TYPE).post(ClientResponse.class, input);
I have tried to set the type to MediaType.APPLICATION_FORM_URLENCODED_TYPE as well as MediaType.APPLICATION_JSON but it doesnt change the response. I am running this code as a standalone executable JAR in a linux environment. Any help is appreciated.
Based on Vijay-Bhushan example in the linked SO article mentioned in my second comment your code should be (and he noted UTF-8 wasnt needed):
String SERVICE_URL = "http://hostIpAddress:8080/JiraUpdate/rest/createin/jira/createticket?"; // hostIpaddress is our server ip
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
System.out.println("SERVICE_URL=" + SERVICE_URL);
WebResource webResource = client.resource(UriBuilder.fromUri(SERVICE_URL).build());
String input = "{\"fields\":{\"project\":{\"key\":\"Invoicing\"},\"summary\":\"REST Test\",\"description\": \"Creating of an issue using project keys and issue type names using the REST API\",\"issuetype\":{\"name\":\"Bug\"}}}";
ClientResponse response = webResource.header("Content-Type","application/json;charset=UTF-8").post(ClientResponse.class,input);
The Jersey Client API documentation has some great examples.

Empty SOAPAction Apache cxf

I'm creating a soap client using apache cxf.I used a network hook capture the data and find out in Http header SOAPAction is empty
SOAPAction : ""
Below is the code
URL wsdlurl=SOAPWebServiceTransport.class.getClassLoader().
getResource("my.wsdl");
OnlinePort service= new OnlinePortService(wsdlurl).getOnlinePortPort();
Client proxy = ClientProxy.getClient(service);
// Provides WS-Security
WSS4JOutInterceptor wss4jOut = new WSS4JOutInterceptor();
wss4jOut.setProperty("action", "UsernameToken");
wss4jOut.setProperty("user", userName);
wss4jOut.setProperty("passwordType", "PasswordText");
wss4jOut.setProperty("password", password);
wss4jOut.setProperty(WSHandlerConstants.ADD_UT_ELEMENTS,
WSConstants.NONCE_LN + " " + WSConstants.CREATED_LN);
wss4jOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordCallback.class.getName());
proxy.getEndpoint().getOutInterceptors().add(wss4jOut);
setConduitProperties((HTTPConduit) proxy.getConduit(),url);
In the setConduitProperties I'm just setting some http properties.
While investigating this issue I found a work around
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("SOAPAction", Arrays.asList("myPrefix:mySoapMethod"));
proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
But the problem is that if I have more than one method then in the Http header its putting all the method
SOAPAction : "myPrefix:mySoapMethod,myPrefix:mySoapMethod2"
Is there any better solution to handle this?
I would suggest to set the SOAPAction header per request. Otherwise, the server is not be able to tell which method do you want to invoke.

Sending POST data to REST service with authentication

I want to send JSON data to a REST service which includes authentication, but when I try to run this code, it throws a RuntimeException and HTTP code 302. But the link is working fine through a REST client. I think my code is unable to provide the authentication details to the link.
I have tried so many combinations, but it's still not working. Can anyone suggest where I am going wrong?
JSONObject obj=new JSONObject(req); //JSON Object
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
Client client = Client.create(clientConfig);
//Authentication filter
client.addFilter(new HTTPBasicAuthFilter("username", "password"));
WebResource webResource = client.resource(
"http://licruleswb-dev.cloudapps.cisco.com/LicenseRules/rest/invokeRule");
ClientResponse response = webResource.accept("application/json").type(
MediaType.APPLICATION_JSON_TYPE).post(ClientResponse.class, obj.toString());
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
This is the error:
ERROR:Exception in thread "main" java.lang.RuntimeException: Failed :
HTTP error code : 302
at Test2.main(Test2.java:64)
Test2 is my class.
What framework are you using? Jersey? You can try setting the basic auth with:
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
});
It seems that you use Jersey REST client. You need to be aware that this approach is deprecated in version 2.5 and removed in version 2.6. In higher versions of Jersey, you need to use this:
// Send with all calls
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(
"username", "password");
or
// Send with a single call
Response response = client.target("http://...").request()
.property(HTTP_AUTHENTICATION_BASIC_USERNAME, "username")
.property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "password").get();
See this link for more details: https://jersey.java.net/documentation/latest/client.html#d0e5181.
You could enable traces in your application or use an external HTTP proxy (like tcpmon) to see the actual sent request (if there is a header Authorization with content).
Hope it helps you,
Thierry

Request sent with version Http/0.9

I am using Apache Commons HttpClient v3.1. All my requests are having correct (default) HTTP version in the request line i.e HTTP/1.1 except for 1 request.
Following Post request gets the requestline as HTTP/0.9:
server : port/cas/v1/tickets/TGT-1-sUqenNbqUzvkGSWW25lcbaJc0OEcJ6wg5DOj3XDMSwoIBf6s7i-cas-1
Body: service=*
I debugged through the http client code and saw the requestline is set to HTTP/1.1 but on the server I see the request coming as HTTP/0.9.
I tried to set the HTTP version explicitly using the HttpMethodParams but that does not help.
Does anyone have an idea what could be wrong?
HttpClient client = new HttpClient();
HostConfiguration hc = client.getHostConfiguration();
hc.setHost(new URI(url, false));
PostMethod method = new PostMethod();
method.setURI(new URI(url, false));
method.getParams().setUriCharset("UTF-8");
method.getParams().setHttpElementCharset("UTF-8");
method.getParams().setContentCharset("UTF-8");
method.getParams().setVersion(HttpVersion.HTTP_1_1);
method.addParameter("service", URLEncoder.encode(service, "UTF-8"));
method.setPath(contextPath + "/tickets/" + tgt);
String respBody = null;
int statusCode = client.executeMethod(method);
respBody = method.getResponseBodyAsString();
Thanks Joachim Sauer. I was able to figure out the problem.
I was using Webscarab as web proxy and it emitted out following message "Got a continuation header but had no previous header line". Looked it up online and found that the problem was in multi-line requestline. I was setting the HTTP version to 1.1 explicitly however there was a trailing '\r\n' in the url which made the requestline look like Http/0.9.
Difference between Http/0.9 and Http/1.0 or other higher protocols is that 0.9 had a simple requestline 'METHOD URL'. Later versions also include the Http version in the request line 'METHOD URL HTTPVERSION'.
Hope it saves someone day!

Problem with passing SOAP headers using Apache CXF client

I am trying to implement a simple client for a webservice, the only problem I am facing with the webservice is, it has a generic endpoint: http://myserver3333.com:8080/ws/services and the way you lookup for web services deployed is via SOAP header.
So, for example, if you try to hit the service vis SOAP UI,
the endpoint I specify is: http://myserver3333.com:8080/ws/services
In the SOAP headers I specific the following:
SERVICE-NAME = MyAwesomeService
OPERATION-NAME = makeMeMoreAwesome
So, how can I do the same thing using apache cxf client?
My current code:
URL wsdlLocation = new URL("http://myserver3333.com:8080/ws/service");
MyAwesomeService service = new MyAwesomeService(wsdlLocation);
MyAwesomeServicePort port = service.getMyAwesomeServiceSOAPPort();
List<Header> headers = new ArrayList<Header>();
Header operationNameHeader = new Header(new QName("OPERATION-NAME"), "makeMeMoreAwesome",
new JAXBDataBinding(String.class));
Header serviceNameHeader = new Header(new QName("SERVICE-NAME"), "MyAwesomeService",
new JAXBDataBinding(String.class));
headers.add(operationNameHeader);
headers.add(serviceNameHeader);
BindingProvider bindingProvider = (BindingProvider)port;
bindingProvider.getRequestContext().put(Header.HEADER_LIST, headers);
MakeMeMoreAwesomeRequest request = new MakeMeMoreAwesomeRequest();
MakeMeMoreAwesomeResponse response = port.makeMeMoreAwesome(request);
System.out.println(response.getAck());
But when I run this, I get this error:
Exception in thread "main" com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
java.io.IOException: Server returned HTTP response code: 500 for URL: http://myserver3333.com:8080/ws/services
java.io.IOException: Server returned HTTP response code: 500 for URL: http://myserver3333.com:8080/ws/services?wsdl
Which is correct because there is no WSDL at that location, it need to follow the soap header to get the service.
Update:
After two points from #Daniel Kulp I am here:
I added a new line: bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://myserver3333.com:8080/ws/services");
And now I get this error:
org.apache.cxf.binding.soap.SoapFault: "http://www.myserver.com/ws/services", the namespace on the "errorMessage" element, is not a valid SOAP version.
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.readVersion(ReadHeadersInterceptor.java:115)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:141)
at org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor.handleMessage(ReadHeadersInterceptor.java:60)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:771)
My assumption is, this error is same as this one. But I am not using ?wsdl. So, any suggestions?
2 comments:
1) You aren't picking up CXF. Check your classpath to make sure CXF is there and not the Sun/Oracle implementation. com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException shows you are picking up the Sun implementation.
2) The URL passed into MyAwesomeService(wsdlLocation) MUST be a URL to the WSDL, not the endpoint itself.

Categories

Resources