Post request response using Camel Netty4 - HTTP operation failed invoking - java

I'm new to Camel and am trying to get a response from a Netty4 route using a POST request. I'd like to send a JSON and return a string extracted from the body.
My rest setup is as follows:
public class Server extends RouteBuilder {
#Override
public void configure() {
String listenAddress = "0.0.0.0";
int listenPort = 8080;
restConfiguration()
.component("netty4-http")
.scheme("http")
.host(listenAddress)
.dataFormatProperty("prettyPrint", "true")
.bindingMode(RestBindingMode.auto)
.port(listenPort);
rest("/")
.post()
.consumes("application/json; charset=UTF-8")
.to("direct:post");
}
}
Within my Camel route I'd like to send the message back using:
#Component
public class RestRoute extends RouteBuilder {
#Autowired
CamelContext context;
#Override
public void configure() {
from("direct:post")
.log("New Request")
.streamCaching()
.setHeader(Exchange.HTTP_METHOD,constant(org.apache.camel.component.http4.HttpMethods.POST))
.setBody().jsonpath("$.Text") // extract text from JSON
.to("http4://0.0.0.0:8080?bridgeEndpoint=true");
However I get the following error: org.apache.camel.http.common.HttpOperationFailedException: HTTP operation failed invoking http://0.0.0.0:8080 with statusCode: 500
I'd appreciate some help!

Oh you should not send the message back, this happens automatic when the routing ends, then the message at that point is used as the response message for the rest.
So remove
.to("http4://0.0.0.0:8080?bridgeEndpoint=true");

Related

Unable to receive the UDP response from device

I'm trying to send the UDP request and receive the response. Spring Integration has the appropriate instruments for such kind of task: UnicastSendingMessageHandler and UnicastReceivingChannelAdapter. I configured it in the following way
#Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
#Bean
#ServiceActivator(inputChannel = "requestChannel")
public UnicastSendingMessageHandler unicastSendingMessageHandler() {
UnicastSendingMessageHandler unicastSendingMessageHandler = new UnicastSendingMessageHandler("239.255.255.250", 1982);
return unicastSendingMessageHandler;
}
#Bean
public UnicastReceivingChannelAdapter unicastReceivingChannelAdapter() {
UnicastReceivingChannelAdapter unicastReceivingChannelAdapter = new UnicastReceivingChannelAdapter(8080);
unicastReceivingChannelAdapter.setOutputChannelName("nullChannel");
return unicastReceivingChannelAdapter;
}
How I send a message (I'm using sendDiscoveryMessage() wherever I want):
#Service
public class DiscoveryService {
private static final String DISCOVERY_MESSAGE = "M-SEARCH * HTTP/1.1\r\n"
+ "HOST: 239.255.255.250:1982\r\n"
+ "MAN: \"ssdp:discover\"\r\n"
+ "ST: wifi_bulb";
private final MessageChannel requestChannel;
public DiscoveryService(final MessageChannel requestChannel) {
this.requestChannel = requestChannel;
}
public void sendDiscoveryMessage() {
requestChannel.send(new GenericMessage<>(DISCOVERY_MESSAGE));
}
}
At this point, I can check the packets via WireShark and ensure that Datagram was sent and the appropriate response was sent too.
The only question is how to receive this response. As far as I understand reading the documentation, I need the method annotated with #ServiceActivator. But I don't understand where (which channel) I should receive the response (in order to correctly specify #ServiceActivator(inputChannel="")). Also, I'm not sure about #ServiceActivator(inputChannel = "requestChannel") I put for UnicastSendingMessageHandler bean.
I tried to create the following method(assuming that the response will come to the same channel):
#ServiceActivator(inputChannel = "requestChannel")
public void receiveResponse(Message<String> response) {
System.out.println(response);
}
but it actually intercepts my own request message (seems logical to me, because I send the request to requestChannel).
So I don't understand how many channels I need (maybe I need 1 for request and 1 for response) and how to create #ServiceActivator to catch the response.
unicastReceivingChannelAdapter.setOutputChannelName("nullChannel");
You are sending the result to nullChannel which is like /dev/null on Unix; you are discarding it.
Use #ServiceActivator(inputChannel = "replyChannel") and
unicastReceivingChannelAdapter.setOutputChannelName("replyChannel");

Show image in jersey ExceptionMapper

I trying to write custom exception mapper for CompletionException and to show image in case of this excption. This is my mapper:
#Provider
public class CustomCompleteExceptionManager implements ExceptionMapper<CompletionException> {
#Override
public Response toResponse(CompletionException e) {
return Response
.status(Response.Status.BAD_REQUEST)
.entity(Paths.get("error.png").toFile())
.type("image/img")
.build();
}
Method toResponse is called when my code throws CompletionException, but browser doesn't displays error.png. I get an error:
This site can’t be reached
The webpage at http://localhost:8080/cf/point might be temporarily down or it may have moved permanently to a new web address.
When I write just String message to Response it works fine:
#Provider
public class CustomCompleteExceptionManager implements ExceptionMapper<CompletionException> {
#Override
public Response toResponse(CompletionException e) {
return Response
.status(Response.Status.BAD_REQUEST)
.entity(e.getMessage())
.build();
}
What could be the problem?
The media type set in response is wrong.
It should be .type("image/png") not image/img.
This is the code when I tested in my local.
return Response
.status(Response.Status.BAD_REQUEST)
.entity(Paths.get("/home","kishore","Pictures","Meme.png").toFile())
.type("image/png")
.build();

Retrofit: How to get request properties in requestInterceptor

I need to apply an Authorization header in a request interceptor, but I need to sign the request method, URI, and date.
Inside the request interceptor I get a RequestInterceptor.RequestFacade, which only has "setter methods"
Is there any way I can get request properties inside a request interceptor?
Ah, did some more googling. The way to do this is to use a client wrapper. Observe...
public class SigningClient implements Client {
final Client wrapped;
public SigningClient(Client client) {
wrapped = client;
}
#Override public Response execute(Request request) {
Request newRequest = sign(request);
return wrapped.execute(newRequest);
}
private void sign(Request request) {
// magic
}
}
Found it here: https://github.com/square/retrofit/issues/185#issuecomment-17819547

Wait for Response on REST Request JAVA

I created a java project with glassfish and posted a simple REST GET service like this:
#Path("/get")
public class Rest {
#Path("test/{user}/")
#GET
public String getTest(#PathParam("user") String id) throws IOException {
//send message to websocket client and wait for response
//return "websocket client response";
}
}
this works fine.
I also have a websocket server implementation in the same project. This implementation allows me to send data to the connected clients.
This is my WebSocket implementation:
#ServerEndpoint("/websocket")
public class WebSocketServer {
#OnOpen
public void onOpen(Session userSession){
System.out.println("Se conecto un nuevo cliente");
Modelo.getInstance().users.add(userSession);
}
#OnMessage
public void onMessage(String message,Session userSession) throws IOException{
String username=(String) userSession.getUserProperties().get("username");
if(username==null){
userSession.getUserProperties().put("username", message);
userSession.getBasicRemote().sendText(Modelo.getInstance().buildJsonData("Servidor","nuevo cliente conectado como: "+message));
}else{
Iterator<Session> iterator=Modelo.getInstance().users.iterator();
while(iterator.hasNext()){
iterator.next().getBasicRemote().sendText(Modelo.getInstance().buildJsonData(username,message));
}
}
}
#OnClose
public void onClose(Session userSession){
Modelo.getInstance().users.remove(userSession);
}
#OnError
public void onError(Throwable t){
t.printStackTrace();
}
}
this works fine too.
When the REST method is called i can send successfully a message to one of my websockets clients.
The thing is that i want to return as the REST response, the data that the WebSocket client sends me.
So...
1)Receive REST GET request in Java Server
2)Send via websocket to the client i want to get the info from
3)Respond the REST GET request with the message the websocket client send me.
How can i accomplish this?
[SOLVED]?
I found a way to do this, please i would like to know what do you think.
I found this article: here about async rest reponses.
So i implemented, its the first thing come to my mind, i save the websocket client message in an array, and the REST request is responded when the array has a message.
#Path("/resource")
#GET
public void asyncGet(#Suspended final AsyncResponse asyncResponse) throws IOException {
Modelo.getInstance().enviarMensaje("5", "escenas");
new Thread(new Runnable() {
#Override
public void run() {
String result = veryExpensiveOperation();
asyncResponse.resume(result);
}
private String veryExpensiveOperation() {
while(Modelo.getInstance().responses.size()==0){
}
String result=Modelo.getInstance().responses.get(0);
Modelo.getInstance().responses.clear();
return result;
// ... very expensive operation
}
}).start();
}
I know there a more things to validate this reponses, but at first it works.
I also edit the websockerserver.java to save in the array the response.
Thank you very much
REST works over HTTP which is a request/response model of communication. Which means you need to send a request in order to get a response. Web Sockets is a full duplex socket model. This means the client or the server can send a message as long as the connection is up. The challenge is you're trying to send a response with REST without a request. You could queue the response from the web socket and then send it back with the next REST response. This would however require the REST client to poll the server periodically since you would not have an indication of when the Web Socket client responded.

Trace SOAP request/responses with JAX-WS on the client side

I'm using JAX-WS reference implementation (2.1.7) and I want to trace SOAP request/responses on the client side. Actually, what I need is to examine some Http headers when I receive the response.
Following these previous questions ( Tracing XML request/responses with JAX-WS and Java JAX-WS web-service client: how log request & response xml? ), I've created my own handler to log when I send a request and receive a response:
public class SHandler implements SOAPHandler<SOAPMessageContext>
{
private static final Logger log = Logger.getLogger(SHandler.class);
#Nullable
#Override
public Set<QName> getHeaders()
{
log.debug(">>>>>>>>>>> GetHeaders");
return null;
}
#Override
public boolean handleMessage(SOAPMessageContext soapMessageContext)
{
log.debug(">>>>>>>>>>> HandleMessage");
return true;
}
#Override
public boolean handleFault(SOAPMessageContext soapMessageContext)
{
log.debug(">>>>>>>>>>> HandleFault");
return true;
}
#Override
public void close(MessageContext messageContext)
{
log.debug(">>>>>>>>>>> Close");
}
}
and I add the handler to the handler chain during the service initialisation:
#WebServiceClient(name = "MyService", targetNamespace = "http://www.whatever.com/", wsdlLocation = "file:/path/to/wsdl")
public class MyService extends Service
{
public MyService(URL wsdlLocation) {
super(...);
initializeBinding();
}
#WebEndpoint(name = "MyOperation")
public MyPort getMyPort() {
return super.getPort(new QName("http://www.whatever.com/", "MyPort"), MyPort.class);
}
private void initializeBinding() {
MyPort port = getMyPort();
BindingProvider bindingProvider = ((BindingProvider) port);
List handlerChain = bindingProvider.getBinding().getHandlerChain();
handlerChain.add(new SHandler());
bindingProvider.getBinding().setHandlerChain(handlerChain);
}
...
}
The problem is that this doesn't work at all on the client side. I don't see any logs and my handler is never executed when I send a request and receive a response.
Notice that there is no specific WSDL related to this issue because I work on an MDA platform that generates client/server artifacts from any WSDL. In addition, I cannot do this at configuration level as all is generated, so I can only do it programmatically (I've been googling this and all the solutions that I find are either the one in the original post or using the handler-chain.xml configuration file).
Am I missing something? Is there any other way of doing this?
Thanks in advance.
If you only want to look at the SOAP messages run with
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
VM argument.
Why not use #HandlerChain(file = "....") annotation?
From my pov, you can not mix constructor- and annotation-based configurations as on-deploy webservice initialization and creating new instance of your service class are performed in absolutely different contexts.
there are 2 tools that you can use to help with this:
soapui
Eclipse tcp/ip monitor
Both tools offer a proxy mode, which intercepts, logs and forwards requests and responses.

Categories

Resources