Get Request Body from a Java 11 HttpRequest [duplicate] - java

In a test, I'd like to look inside the body of a HttpRequest. I'd like to get the body as a string. It seems that the only way to do that, is to subscribe to the BodyPublisher but how does that work?

This is an interesting question. Where do you get your HttpRequest from? The easiest way would be to obtain the body directly from the code that creates the HttpRequest. If that's not possible then the next thing would be to clone that request and wraps its body publisher in your own implementation of BodyPublisher before sending the request through the HttpClient. It should be relatively easy (if tedious) to write a subclass of HttpRequest that wraps an other instance of HttpRequest and delegates every calls to the wrapped instance, but overrides HttpRequest::bodyPublisher to do something like:
return request.bodyPublisher().map(this::wrapBodyPublisher);
Otherwise, you might also try to subscribe to the request body publisher and obtain the body bytes from it - but be aware that not all implementations of BodyPublisher may support multiple subscribers (whether concurrent or sequential).
To illustrate my suggestion above: something like below may work, depending on the concrete implementation of the body publisher, and provided that you can guard against concurrent subscriptions to the body publisher. That is - in a controlled test environment where you know all the parties, then it might be workable. Don't use anything this in production:
public class HttpRequestBody {
// adapt Flow.Subscriber<List<ByteBuffer>> to Flow.Subscriber<ByteBuffer>
static final class StringSubscriber implements Flow.Subscriber<ByteBuffer> {
final BodySubscriber<String> wrapped;
StringSubscriber(BodySubscriber<String> wrapped) {
this.wrapped = wrapped;
}
#Override
public void onSubscribe(Flow.Subscription subscription) {
wrapped.onSubscribe(subscription);
}
#Override
public void onNext(ByteBuffer item) { wrapped.onNext(List.of(item)); }
#Override
public void onError(Throwable throwable) { wrapped.onError(throwable); }
#Override
public void onComplete() { wrapped.onComplete(); }
}
public static void main(String[] args) throws Exception {
var request = HttpRequest.newBuilder(new URI("http://example.com/blah"))
.POST(BodyPublishers.ofString("Lorem ipsum dolor sit amet"))
.build();
// you must be very sure that nobody else is concurrently
// subscribed to the body publisher when executing this code,
// otherwise one of the subscribers is likely to fail.
String reqbody = request.bodyPublisher().map(p -> {
var bodySubscriber = BodySubscribers.ofString(StandardCharsets.UTF_8);
var flowSubscriber = new StringSubscriber(bodySubscriber);
p.subscribe(flowSubscriber);
return bodySubscriber.getBody().toCompletableFuture().join();
}).get();
System.out.println(reqbody);
}
}

Related

When many Akka Actors send messages to one actor, how to cleanly handle inheritance of inner Command classes

In akka-typed, the convention is to create Behavior classes with static inner classes that represent the messages that they receive. Heres a simple example
public class HTTPCaller extends AbstractBehavior<HTTPCaller.MakeRequest> {
public interface Command {}
// this is the message the HTTPCaller receives
public static final class MakeRequest implements Command {
public final String query;
public final ActorRef<Response> replyTo;
public MakeRequest(String query, ActorRef<Response> replyTo) {
this.query = query;
this.replyTo = replyTo;
}
}
// this is the response message
public static final class Response implement Command {
public final String result;
public Response(String result) {
this.result = result;
}
}
public static Behavior<Command> create() {
return Behaviors.setup(HTTPCaller::new);
}
private HTTPCaller(ActorContext<Command> context) {
super(context);
}
#Override
public Receive<Command> createReceive() {
return newReceiveBuilder()
.onMessage(MakeRequest.class, this::onMakeRequest).build();
}
private Behavior<MakeRequest> onMakeRequest(MakeRequest message) {
String result = // make HTTP request here using message.query
message.replyTo.tell(new Response(result));
return Behaviors.same();
}
}
Let's say that 20 other actors send MakeRequest messages to the single HTTPCaller actor. Now, each of these other actors have inner classes that implement their own Command. Since MakeRequest is being used by all 20 classes it must be a subtype of all 20 of those actors' Command inner interface.
This is not ideal. I'm wondering what the Akka way of getting around this is.
There's no requirement that a message (e.g. a command) which an actor sends (except for messages to itself...) have to conform to that actor's incoming message type. The commands sent to the HTTPCaller actor only have to (and in this case only do) extend HTTPCaller.Command.
So imagine that we have something like
public class SomeOtherActor extends AbstractBehavior<SomeOtherActor.Command> {
public interface Command;
// yada yada yada
ActorRef<HTTPCaller.Command> httpCallerActor = ...
httpCallerActor.tell(new HTTPCaller.MakeRequest("someQuery", getContext().getSystem().ignoreRef());
}
In general, when defining messages which are sent in reply, those are not going to extend the message type of the sending actor. In HTTPCaller, for instance, Response probably shouldn't implements Command: it can be a standalone class (alternatively, if it is something that might be received by the HTTPCaller actor, it should be handled in the receive builder).
My code above does bring up one question: if Response is to be received by SomeOtherActor, how can it extend SomeOtherActor.Command?
The solution there is message adaptation: a function to convert a Response to a SomeOtherActorCommand. For example
// in SomeOtherActor
// the simplest possible adaptation:
public static final class ResponseFromHTTPCaller implements Command {
public final String result;
public ResponseFromHTTPCaller(HTTPCaller.Response response) {
result = response.result;
}
// at some point before telling the httpCallerActor...
// apologies if the Java lambda syntax is messed up...
ActorRef<HTTPCaller.Response> httpCallerResponseRef =
getContext().messageAdapter(
HTTPCaller.Response.class,
(response) -> { new ResponseFromHTTPCaller(response) }
);
httpCallerActor.tell(new HTTPCaller.MakeRequest("someQuery", httpCallerResponseRef);
There is also the ask pattern, which is more useful for one-shot interactions between actors where there's a timeout.

Class variable vs passing parameter in java - design issue

Say I have 2 classes in an SOA model application..
Service class - which takes request and returns response
For further processing (say, business logic/parsing/dao etc), it passes the request to a SvcBusiness class.
Question is, should SvcBusiness class use the request as its class variable or should it just use the request in one of it's business methods? It is possible that request needs to be passed to other lower layers like DAO layer. Should those classes also use request as a class variable or should the request be just part of a method?
ServiceImpl class:
public class ServiceImpl {
public Response getDataForType1Request(Request type1) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType1(type1);
}
public Response getDataForType2Request(Request type2) {
SvcBusiness buzclazz = new SvcBusiness();
return buzclazz.doOperationForType2(type2);
}
}
Option 1: when request is passed as a parameter.
public class SvcBusiness {
public Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}
Option 2: request is set as a class variable. In this scenario.. ServiceImpl will pass the request to SvcBusiness constructor when the object is created.. and will simply call execute() method.
public class SvcBusiness {
private Request request;
public SvcBusiness(Request request) {
this.request = request;
}
private Response doOperationForType1() {
// do business and return response1
}
private Response doOperationForType2() {
// do business and return response2
}
public Response execute() {
// if type1 request call doOperationForType1()
// if type2 request call doOperationForType1()
}
}
Please help! What are the advantages and disadvantages of both? Is there a design pattern to address this scenario?
Don't use the Request (and Response) further down in your class hierarchy! The service (and everything called by the service) may be called from somewhere else, where there is no such thing as a Request. And then you will have a problem with filling that parameter. Use an own data model in the service, and extract and convert everything you need for that from the Request.
Fully agree with Uwe's answer. However, if you still want to use Request class, it'll be less harmful as a parameter (The way Servlets work). Otherwise, you'd have to deal with synchronization on a highly probable multithreaded environment.
When I face a problem like this I always wonder if I really need an object. Usually I use the option 1 but creating all methods as static. As those methods don't rely in the current object state (there are no instance attributes), I save some memory just not creating such objects (other option is just implement the Singleton pattern).
public class SvcBusiness {
public static Response doOperationForType1(Request type1) {
// do business and return response1
}
public Response doOperationForType2(Request type2) {
// do business and return response2
}
}

Mocking inside a Java class

So I have this GWT code that handles RPC requests maintain states(ready, waiting, error etc).
And I would like to check if the class change its states correctly after each call, set response variables etc.
Now how should I proceed to test that without making actual requests to the server(that could run into errors in the server it self).
I think I could mock the request callback class somehow but it is invisible to the test.
I'm lost, help!
Sample of the code below(I'll post the whole thing later in case anyone wants).
public class RPCHandler
{
public RPCHandler(String method,String[] argumentsName,
String[][] argumentsValues)
{
this.method = method;
this.argumentsName = argumentsName;
this.argumentsValues = argumentsValues;
}
/**
* Method that creates a RPC request using JSON in a POST
*
*/
public void rpcRequest(){
if(currentState == HandlerState.WAITING_RESPONSE)return;
currentState = HandlerState.WAITING_RESPONSE;
// Append watch list stock symbols to query URL.
url = URL.encode(url);
url += "action=";
url += method;
// Send request to server and catch any errors.
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
String requestData = parseToJSON(argumentsName, argumentsValues);
try{
Request request = builder.sendRequest(requestData, new RequestCallback()
{
public void onError(Request request, Throwable exception)
{
setRPCException(new Exception("Error while saving. Action="+method));
setCurrentState(HandlerState.ON_ERROR);
}
//Few other error, response received hander methods after this point.
}
}
It looks like you're trying to mock out the actual transport so you should build a mock of the RequestBuilder class. In JMockit, you could write:
public class MockRequestBuilder
{
public void $init( int method, String url)
{
/* check values and/or store for later */
}
public Request sendRequest( String data, RequestCallback callback )
{
/* check values and/or store for later */
}
}
You'll need to fill in the details of the what you want the mock to do. Also, you can isolate the callback testing if you moved the callback to a named class instance inside of your outer class:
public class MyGWTClass
{
protected static class RpcCallback extends RequestCallback
{
public void onError(...) { ... }
}
}
By moving the callback object into a class and using a factory method, you can create tests that only check the callback.

Avoiding instanceof when checking a message type

I have the following situation where a client class executes different behavior based on the type of message it receives. I'm wondering if there is a better way of doing this since I don't like the instanceof and the if statements.
One thing I thought of doing was pulling the methods out of the client class and putting them into the messages. I would put a method like process() in the IMessage interface and then put the message specific behavior in each of the concrete message types. This would make the client simple because it would just call message.process() rather than checking types. However, the only problem with this is that the behavior contained in the conditionals has to do with operations on data contained within the Client class. Thus, if I did implement a process method in the concrete message classes I would have to pass it the client and I don't know if this really makes sense either.
public class Client {
messageReceived(IMessage message) {
if(message instanceof concreteMessageA) {
concreteMessageA msg = (concreteMessageA)message;
//do concreteMessageA operations
}
}
if (message instanceof concreteMessageB) {
concreteMessageb msg = (concreteMessageB)message;
//do concreteMessageB operations
}
}
The simple way to avoid instanceof testing is to dispatch polymorphicly; e.g.
public class Client {
void messageReceived(IMessage message) {
message.doOperations(this);
}
}
where each message class defines an appropriate doOperations(Client client) method.
EDIT: second solution which better matches the requirements.
An alternative that replaces a sequence of 'instanceof' tests with a switch statement is:
public class Client {
void messageReceived(IMessage message) {
switch (message.getMessageType()) {
case TYPE_A:
// process type A
break;
case TYPE_B:
...
}
}
}
Each IMessage class needs to define an int getMessageType() method to return the appropriate code. Enums work just as well ints, and are more more elegant, IMO.
One option here is a handler chain. You have a chain of handlers, each of which can handle a message (if applicable) and then consume it, meaning it won't be passed further down the chain. First you define the Handler interface:
public interface Handler {
void handle(IMessage msg);
}
And then the handler chain logic looks like:
List<Handler> handlers = //...
for (Handler h : handlers) {
if (!e.isConsumed()) h.handle(e);
}
Then each handler can decide to handle / consume an event:
public class MessageAHandler implements Handler {
public void handle(IMessage msg) {
if (msg instanceof MessageA) {
//process message
//consume event
msg.consume();
}
}
}
Of course, this doesn't get rid of the instanceofs - but it does mean you don't have a huge if-elseif-else-if-instanceof block, which can be unreadable
What type of message system are you using?
Many have options to add a filter to the handlers based on message header or content. If this is supported, you simply create a handler with a filter based on message type, then your code is nice and clean without the need for instanceof or checking type (since the messaging system already checked it for you).
I know you can do this in JMS or the OSGi event service.
Since you are using JMS, you can basically do the following to register your listeners. This will create a listener for each unique message type.
String filterMsg1 = "JMSType='messageType1'";
String filterMsg2 = "JMSType='messageType2'";
// Create a receiver using this filter
Receiver receiverType1 = session.createReceiver(queue, filterMsg1);
Receiver receiverType2 = session.createReceiver(queue, filterMsg2);
receiverType1.setMessageHandler(messageType1Handler);
receiverType2.setMessageHandler(messageType2Handler);
Now each handler will receive the specific message type only (no instanceof or if-then), assuming of course that the sender sets the type via calls to setJMSType() on the outgoing message.
This method is built into message, but you can of course create your own header property and filter on that instead as well.
//Message.java
abstract class Message{
public abstract void doOperations();
}
//MessageA.java
class MessageA extends Message{
public void doOperations(){
//do concreteMessageA operations ;
}
}
//MessageB.java
class MessageB extends Message {
public void doOperations(){
//do concreteMessageB operations
}
}
//MessageExample.java
class MessageExample{
public static void main(String[] args) {
doSmth(new MessageA());
}
public static void doSmth(Message message) {
message.doOperations() ;
}
}
A Java 8 solution that uses double dispatch. Doesn't get rid of instanceof completely but does only require one check per message instead of an if-elseif chain.
public interface Message extends Consumer<Consumer<Message>> {};
public interface MessageA extends Message {
#Override
default void accept(Consumer<Message> consumer) {
if(consumer instanceof MessageAReceiver){
((MessageAReceiver)consumer).accept(this);
} else {
Message.super.accept(this);
}
}
}
public interface MessageAReceiver extends Consumer<Message>{
void accept(MessageA message);
}
With JMS 2.0 you can use:
consumer.receiveBody(String.class)
For more information you can refer here:

How to nest Spring JMS MessageConverters

I'd like to write a MessageConverter class that can wrap another MessageConverter. This MessageConverter would call the child converter, which is assumed to generate a TextMessage. It would take the payload and GZIP compress it, creating a BytesMessage which is ultimately returned to the sender.
The problem is in writing fromMessage(). I can convert the payload back into the string, but then I want to create a "dummy" TextMessage to stuff the string into to then pass to the child MessageConverter's fromMessage() method. There I'm hitting a brick wall because I can't create a TextMessage without a JMS session object, and it appears that there is no way at all to get a session in this context.
I could create additional properties to wire up more stuff to this class, but it doesn't look like I can easily even obtain a session from a JMSTemplate object, and I can't imagine what else I'd need to have.
I am on the verge of creating a private TextMessage implementation within this code just for the purpose of wrapping a string for the child MessageConverter. That class will require tons of dummy methods to flesh out the Interface, and all of that typing makes baby Jesus cry.
Can anyone suggest a better way?
Do you really wanna wrap MessageConverter instances inside other MessageConverter instances? The whole point of a MessageConverter is to turn a Message into something else (that is not a JMS Message). Its not really designed to chain them (each step making a fake JMS message).
Why not just introduce your own interface
interface MessageBodyConverter {
/** return a converted body of the original message */
Object convert(Object body, Message originalMessage);
}
You then can create a MessageConverter invoking one of these (which can then nest as deep as you like)
class MyMessageConverter implements MessageConverter {
private final MessageBodyConverter converter;
public Object fromMessage(Message message) {
if (message instanceof ObjectMessage) {
return converter.convert(objectMessage.getObject(), message);
...
}
}
You can then chain those MessageBodyConverter objects as deep as you like - plus you have access to the original JMS message (to get headers and so forth) without having to try create pseudo (probably not JMS compliant) implementations of Message?
So I did, in fact, make one of these:
private static class FakeTextMessage implements TextMessage {
public FakeTextMessage(Message m) { this.childMessage = m; }
private String text;
private Message childMessage;
public void setText(String t) { this.text = t; }
public String getText() { return this.text; }
// All the rest of the methods are simply pass-through
// implementations of the rest of the interface, handing off to the child message.
public void acknowledge() throws JMSException { this.childMessage.acknowledge(); }
public void clearBody() throws JMSException { this.childMessage.clearBody(); }
public void clearProperties() throws JMSException { this.childMessage.clearProperties(); }
public Enumeration getPropertyNames() throws JMSException { return this.childMessage.getPropertyNames(); }
public boolean propertyExists(String pn) throws JMSException { return this.childMessage.propertyExists(pn); }
// and so on and so on
}
Makes me long for Objective C. How is THAT possible? :)

Categories