We are sending a byte array to a REST API we do not control.
The REST API requires the byte array to be sent as the body.
The code is as follows:
String path = "/dokumente/angebote/{angebotsId}/unterlagen/{dokumentId}";
WebTarget target = createWebTarget().path(path).resolveTemplate("angebotsId", angebotsId).resolveTemplate("dokumentId", documentType);
try (ResponseHandler handler = new ResponseHandler(
target.request(document.getMimeType()).header("Content-Type", document.getMimeType())
.post(Entity.entity(MY_BYTE_ARRAY))) {
Response response = handler.getResponse();
...
}
This has worked well so far, we have been using JBoss and RestEasy. We have now migrated our application to OpenLiberty, which means that Apache CXF will be used as JAX-RS implementation.
And since the migration, the implementation does not work anymore. We found out that if we use a wrapper class like that:
MyWrapper myByteArrayWrapper = new MyWrapper();
myByteArrayWrapper.setData(MY_BYTE_ARRAY));
.post(Entity.entity(myByteArrayWrapper))
then Apache CXF will successfully transfer the byte array, but this does not comply to the API definition of the service we are calling.
Has anybody succeeded in getting a byte[] upload running with Apache CXF?
The problem was that OLP (in contrast to JBoss) used chunked transfer. The server that we called did not support that. Chunked transfer was now enabled on the other server, and now everything works.
Related
I've set up #MessageMapping endpoint using Spring's RSocket support and tested it with RSocketRequester. This flow is working perfectly since Spring handles bunch of low-level stuff for us.
Now, I'd like to have some sort of UI to show whatever data I'm working with and do any UI updates on that data through mentioned #MessageMapping endpoint. The problem is that I have no idea how to send full Java/Kotlin object (as JSON) to my endpoint using either rsocket-java or rsocket-kotlin libraries. Since I have to send both data and metadata and metadata is encoded as ByteBuf I had to encode JSON to ByteBuf, but it comes to endpoint all messed up and it cannot be deserialized.
I've also tried sending raw string value and it also comes to endpoint all messed up (bunch of non-UTF chars). I've tried both APPLICATION_JSON and TEXT_PLAIN for data mime type, but it didn't work for either.
Also, I guess whatever I'm doing wrong is not strictly related to Java/Kotlin libraries, but can be applied to any other existing RSocket library (Go, Rust, JS, etc.)
If you are using an rsocket-kotlin client (not building on spring-boot) then you can copy the code from https://github.com/rsocket/rsocket-cli/blob/master/src/main/kotlin/io/rsocket/cli/Main.kt
It builds metadata for the route with
this.route != null -> {
CompositeMetadata(RoutingMetadata(route!!)).toPacket().readBytes()
}
I guess I've figured it out.
I've scratched that binary encoded metadata and borrowed what I found on the internet for RSocket in JavaScript and it worked :)
So, the solution is to use routing metadata mime type (I was using composite since example I found was using it) and the payload then can be created like this:
val json = "{}"
val route = "myawesomeroute"
DefaultPayload.create(<json>, "${route.length.toChar()}$route")
I'm working with a large existing project, which utilises javax.ws.rs.client.WebTarget to talk to RESTful API. The API is developed by a third party and I have no control over it. I need to make a request in the following format:
https://end.point.url/endpoint/id?data
Unfortunately, I can't figure out how to specify such request using WebTarget. I tried using path("endpoint/id?data"), but this gets converted into endpoint/id%3Fdata and I get 404 back. I tried using queryParam specifying empty value, which gets me endpoint/id?data= - which results in error required parameter data missing.
What other option is there? Replacing WebTarget with something else isn't feasible, as it is all over the large project.
First, related question: Url encoding issue with Jersey Client
After quite a bit of research, it seems that the only way to do it is to specify the entire uri when the WebTarget is created, like so:
Client client = ClientBuilder.newClient().register(authFeature);
WebTarget webTarget = client.target("https://end.point.url/endpoint/id?data")
We recently upgraded from Jersey 1.x to 2.x and most of the migration went smoothly. There's one snag though.
In 1.x, the following code would let us grab the InputStream while the server was still writing to its respective OutputStream:
final ClientResponse response = webResource
.accept(acceptHeader)
.get(ClientResponse.class);
final InputStream stream = response.getEntity(InputStream.class);
/* Process the stream, waiting if necessary */
We are using this as a sort of server-send event (before we found out about sse), but a similar and more common problem would be downloading a large file. The Jersey 2.x code looks like:
final Response response = webTarget
.request()
.accept(acceptHeader)
.get(); /* debug shows this call hanging */
final InputStream stream = response.getEntity(InputStream.class);
/* Process the stream, waiting if necessary */
The get() method hangs because the server never closes the connection. Fortunately in our case, the server is just waiting for "events" to send to the client, but if the client were downloading say a 64 GB file...
Turns out the problem was on the server side.
In Jersey 1.x, the server was not buffering the response (or we had overridden that behavior and forgotten). The solution was to set the property jersey.config.contentLength.buffer to 0. This prevented the server from buffering, and the code listed in this question worked without modification.
I am trying to create a java application to read the information from ARIN using an IP Address. I see ARIN is using RESTful Web Services to get the IP information but I am not sure what I need to do to start. Some people are talking about RESTLET, other people about JAX-RS,etc. Can you please help me to take me in the right direction? Thanks!
Restlet also has a client API to interact with a remote RESTful application. See the classes Client, ClientResource for more details. For this, you need to have following jar files from Restlet distribution:
org.restlet: main Restlet jar
org.restlet.ext.xml: Restlet support of XML
org.restlet.ext.json: Restlet support of JSON. In this case, the JSON jar present in libraries folder is also required.
If I use the documentation located at this address https://www.arin.net/resources/whoisrws/whois_api.html#whoisrws. Here is a simple Restlet code you can use:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get();
// Display the XML content
System.out.println(repr.getText());
or
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN.txt");
Representation repr = cr.get();
// Display the text content
System.out.println(repr.getText());
Restlet also provides some support at XML level. So you can have access to hints contained in the XML in a simple way, as described below:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get();
DomRepresentation dRepr = new DomRepresentation(repr);
Node firstNameNode = dRepr.getNode("//firstName");
Node lastNameNode = dRepr.getNode("//lastName");
System.out.println(firstNameNode.getTextContent()+" "+lastNameNode.getTextContent());
Note that you can finally handle content negotiation (conneg) since it seems supported by your REST service:
ClientResource cr = new ClientResource("http://whois.arin.net/rest/poc/KOSTE-ARIN");
Representation repr = cr.get(MediaType.APPLICATION_JSON);
In this case, your representation object contains JSON formatted data. In the same way than the DomRepresentation, there is a JsonRepresentation to inspect this representation content.
Hope it helps you.
Thierry
The problem is that you don't seem to understand very well what REST is (sorry if I'm mistaken!). Restlet and JAX-RS are both server-side related.
You probably need something like jersey-client. This is a library which helps to interact with RESTful webservices.
You could also usa plain Java libraries to make HTTP calls to the webservice. REST is tightly bound to its implementation protocol. This means that if the webservice is implemented in HTTP (most likely is) you don't need anything fancy to interact with it. Just HTTP.
I strongly encourage you to learn more about REST and HTTP itself.
I am trying to get the raw XML response from a web service, instead of the usual set of POJOs.
I am using a webservice client that I generated (so I have access to the client's code) from a WSDL and some schemas. The client is generated in RAD 7.5, I think using JAX-WS. I've been looking at the client code itself, but I'm not even sure if the client code ever handles raw XML or if it passes it off to other libraries.
You can do it using
javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>
you can simply get message using SOAPMessageContext#getMessage() and convert message to String using method
public static String getXmlMessage(SOAPMessage message) throws Exception
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
final String encoding = (String) message.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (encoding == null)
{
return new String(os.toByteArray());
}
else
{
return new String(os.toByteArray(), encoding);
}
}
Also you can read here about SOAP handler on client side
Article
It's not widely documented, but you can use the Dispatch interface to implement JAXWS clients which work directly w/ the XML. Here and here are some articles for getting started.