Calling Camlet RESTLET Server with Apache HTTp Client - rest

This one should be trivial but somehow it is not working for me. I am trying to make a call to a RESTLET server hosted on Camel. I get it working with Camel client but I am trying to get the same to work with a bare Apache HTTP Client. The Camel is client is as follows:
CamelContext context = new DefaultCamelContext();
Map<String, Object> headers = new HashMap<String, Object>();
context.createProducerTemplate().requestBodyAndHeaders("restlet:http://localhost:8086/Bookmarkee/boolean/V2?restletMethod=post", "Halleluia",headers);
The HTTP Client I am trying to make work is this:
HttpPost httppost = new HttpPost("http://localhost:8086/Bookmarkee/boolean/V2?restletMethod=post");
StringEntity e= new StringEntity("Halleluia",ContentType.create("text/plain", "UTF-8"));
httppost.setEntity(e);
CloseableHttpResponse response = httpclient.execute(httppost);
On the server however, the response is not read from the stream by the servlet engine. Resulting in my component being passed an input stream instead of a string.
Any clue?

Experienced same problem when my camel route tried to process empty response from server (200 OK, Content-Length:0, Content-Type:application/json)
Fixed after I found and fixed bug in URL which I used for requesting with http component

Related

Returning bytes[] and Java Object in Jersey in same Http Response

I have to return byte[] as file data and JSON object both in a http response from a REST service.
Also I have to process this response in Angular 6 at front end side
The REST service uses Jersey 2.0
I have already implemented the Jersey Rest Service and it returns Multipart Response
But I am unable to process the Multipart response in Angular 6 as HttpClient in Angular cannot process MultiPart Response as per Handling a multipart Response body in Angular
Now , I have done exactly same thing in Spring by using org.springframework.util.MultiValueMap as below -
MultiValueMap<String, Object> responseData = new LinkedMultiValueMap<String, Object>();
SomeDto someDto = new SomeDto();
responseData.add("results", someDto); // this is JSON
responseData.add("fileDetails", fileData); // where fileData has one of the field
as byte[]
So I am able to return byte[] as well as Java Object in same Http Response.
Finally the response received at client side is JSON
How can we achieve the same thing in Jersey 2 ?
Is there any MultiValueMap counterpart in Jersey 2 which can be used to send both byte[] and Java Object in Jersey 2 ?

Livy REST API: GET requests work but POST requests fail with '401 Authentication required'

I’ve written a Java client for parts of Livy’s REST API at https://github.com/apache/incubator-livy/blob/master/docs/rest-api.md. The client uses Spring’s RestTemplate.getForObject() and postForObject() to make GET and POST requests respectively. The Livy server is secured with Kerberos.
GET /sessions and GET /batches requests work fine: I get the expected responses from Livy. But both POST /sessions and POST /batches requests fail with:
org.springframework.web.client.HttpClientErrorException: 401 Authentication required
Does anyone know why the POST requests fail when the GET requests succeed? My code does nothing explicit with authentication.
I've tried authenticating as several different users via Kerberos but I always get this problem. Does Livy need extra configuration to allow POST requests from particular users (since POST requests effectively create interactive sessions or submit jobs to Spark)?
It turns out that whilst the regular org.springframework.web.client.RestTemplate class is sufficient for GET requests, you need to use org.springframework.security.kerberos.client.KerberosRestTemplate for POST requests. You may also need to add an extra header to POST requests if the Livy server has CSRF (cross-site request forgery) protection enabled as described here.
GET /batches example
RestTemplate restTemplate = new RestTemplate();
GetBatchesResponse response2 = restTemplate.getForObject("http://your_livy_server:8998" + "/batches", GetBatchesResponse.class);
where GetBatchesResponse is a simple POJO I've written that represents the response body to GET /batches.
POST /batches example
PostBatchesRequest postRequestBody = new PostBatchesRequest();
postRequestBody.setFile("/path/to/your/application"); // In HDFS
KerberosRestTemplate kerberosRestTemplate = new KerberosRestTemplate("path_to_your_key_tab_file", "your_user#your_realm");
// Add CSRF header if required:
HttpHeaders headers = new HttpHeaders();
headers.set("X-Requested-By", "your_user#your_realm");
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<PostBatchesRequest> postRequest = new HttpEntity<PostBatchesRequest>(postRequestBody, headers);
Batch batch = kerberosRestTemplate.postForObject("http://your_livy_server:8998" + "/batches", postRequest, Batch.class);
where PostBatchesRequest and Batch are POJOs I've written to represent the request body and response respectively.

SOAP header for authentication in Notes/Domino

I need to consume a WS that requires client (machine) certificate. More precisely it uses WS-Security : SOAP Message Security, WS-Security : X.509 Certificate Token Profile as defined by http://docs.oasis-open.org/wss-m/wss/v1.1.1/os/wss-SOAPMessageSecurity-v1.1.1-os.html
Using the native consumer, Domino don't add (magically) the authentication in the SOAP header. Now how I'm supposed to do add the security in header? Ideally in LotusScript...
I don't see anyway to embed the Consumer in my own header or enrich the existing consumer. I join the IBM response on this.
So my question:
Is there a work around to do this in Lotusscript ?
did some of you done something like this in java (and I will probably make an LS2J since a lot of LotusScript code already exists when I will get (hopefully) the response from the WS
IBM response:
We understand that you are attempting to use SOAP header for authentication. Unfortunately this is currently not supported.
For your reference, we have at least two Enhancement Requests (that I could find in this area) that are related to this topic:
SPR # SODY9H6BTM: Creating Your Own Soap Objects Does Not Support Client Certificate Authentication In A Web Agent.
SPR # JSHN7A3MLP: Authentication data in the Header element of WS Consumer SOAP envelopes
Unfortunately there is nothing further we can do in Support at this time.
If I understood your problem correctly you do not know how to deal with SOAP header and if so there are 2 things you may want to know:
1) Passing session using native Domino consumer approach. See example below
TestServiceLocator service = new TestServiceLocator();
TestPort port = service.getTestPort();
// that would tell to save cookie session between calls
((javax.xml.rpc.Stub)port)._setProperty(javax.xml.rpc.Stub.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
2) If it does not work for you, you may try to use native SOAP approach. I've blogged about that recently: SOAP and passing session
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// connect to webserivce
SOAPMessage soapResponse = soapConnection.call(connect(username, password), url);
// read cookie from response and use it when send another requests
MimeHeaders session = soapResponse.getMimeHeaders();
String sesisonCookie = session.getHeader("Set-Cookie")[0];
SOAPMessage soapResponse2 = soapConnection.call(customerGetAll(sesisonCookie), url);
soapConnection.close();
and than imagine you are in customGetAll method
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("Customer_GetAll", "m");
soapMessage.getMimeHeaders().addHeader("Cookie", sesisonCookie);
soapMessage.saveChanges();
Hope it will help.

Use GWT RPC Serialization to send an object from client to server in a POST

I prefer to use RPC Serialization but then send data using servlets.
We have strangely found that this performs better and it allows us to have general logic for retrying all servlet calls for example.
I have figured out how to send an object from server to client but can't find a way to serialize on client and deserialize on server.
SERVER TO CLIENT
Server:
serializedObj = RPC.encodeResponseForSuccess(DUMMY_METHOD_OF_TYPE_SERIZABLE, object);
Client:
GWT.create(MyRpc.class).createStreamReader(serializedObj).readObject();
CLIENT TO SERVER
Client:
SerializationStreamWriter streamWriter = streamFactory.createStreamWriter();
streamWriter.writeObject(object);
serializedObj = streamWriter.toString();
But how can I unserialize this after sending it by POST to the server?
Thanks!
http://softteco.blogspot.com/2010/02/serializing-objects-in-gwt-and.html
Note the server side deserialize option
// Getting parameter from request
String content = request.getParameter("content");
// Initializing stream reader
ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
Thread.currentThread().getContextClassLoader(), null);
// Filling stream reader with data
streamReader.prepareToRead(content);
// Reading deserialized object from the stream
dto = (D) streamReader.readObject();

CXF JAXRS client not reusing TCP connections

I'm using the JAX-RS support in CXF 2.2.5 to invoke REST webservices. I'm creating a single org.apache.cxf.jaxrs.client.WebClient instance for each endpoint I need to communicate with (typically one or two endpoints for any given deployment) and re-using this client for each web-service invocation.
The problem I face is that the client is creating new TCP connections to the server for each request, despite using the keep-alive setting. At high traffic levels, this is causing problems. An excerpt from my client code is below.
I'm trying to dig through the CXF source to identify the problem but getting hopelessly lost at present. Any thoughts greatly appreciated.
Thanks,
FB
ConcurrentMap<String, WebClient> webclients = new ConcurrentHashMap<String, WebClient>();
public void dispatchRequest(MyRequestClass request, String hostAddress) {
// Fetch or create the web client if we don't already have one for this hostAddress
// NOTE: WebClient is only thread-safe if not changing the URI or headers between calls!
// http://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-ThreadSafety
WebClient client = webclients.get(hostAddress);
if (client == null) {
String serviceUrl = APP_HTTP_PROTOCOL + "://" + hostAddress + ":" + APP_PORT + "/" + APP_REQUEST_PATH;
WebClient newClient = WebClient.create(serviceUrl).accept(MediaType.TEXT_PLAIN);
client = webclients.putIfAbsent(hostAddress, newClient);
if (client == null) {
client = newClient;
} // Else, another thread must have added the client in the meantime - that's fine if so.
}
XStream marshaller = MyCollection.getMarshaller();
String requestXML = marshaller.toXML(request);
Response response = null;
try {
// Send it!
response = client.post(requestXML);
}
catch (Exception e) {
}
...
}
In your sample code you get a JAX-RS Response, which getEntity() method will return an InputStream by default. Therefore, being CXF not responsible for consuming the stream, this is obviously left open.
If you don't explicitly close that, it would be closed during a Garbage Collection phase.
But even so, under high traffic rates, this little latency prevents the underlying HTTP connection to be reinserted into the internal pool of persistent connections exploited by HttpURLConnection (that CXF is using under the bonnet). So it cannot be reused on time.
If you take care of closing the InputStream, you should not see a large number of TIME_WAIT sockets anymore.
I would definitely try updating to a newer and supported version of CXF. There have been a LOT of updates to the JAX-RS stuff in the newer versions of CXF and this issue may already be fixed.