Spring Rest Controller: Accept single object and array under one URL - java

Assuming there is a REST Controller with an endpoint that accepts a single object in the body:
#PostMapping("/ExampleObjects")
void mapping(#RequestBody ExampleObject object){ ....
If one would want to add the ability to accept an array under the same endpoint like this:
#PostMapping("/ExampleObjects")
void mapping(#RequestBody ExampleObject[] objects){ ....
Is there a way to implement the new functionality with the given design and without breaking existing users?

That should help you.
application.properties:
spring.jackson.deserialization.accept-single-value-as-array=true
controller:
#PostMapping("/ExampleObjects")
void mapping(#RequestBody List<ExampleObject> objects){ ....

How about having the first endpoint called "/ExampleObject" instead, seeing as it appears to be singular?

It's good practise to keep your API endpoints as simple as possible, as consistent as possible (between different endpoints in the single API), and as error-tolerant as possible.
Instead of an array, you'd want to use a generic List<ExampleObject> in any case.
You could just implement the list version of the method, call that method with a list that only contains a single instance. You'd want to think about the consistency part of the equation a little bit. What kinds of different endpoints will you be implementing in your API. Would this solution fit most of those use cases?
Go with the solution that results with the least surprises to your API users.

Currently something like Jackson is doing the parsing from HTTP request body to ExampleObject automatically for you.
You could do the parsing in your code and decide during parsing, if it is an instance of ExampleObject or ExampleObject[]. Therefore you would have one method with this signature:
#PostMapping("/ExampleObjects")
void mapping(#RequestBody String objectOrArray){
// code to parse String into ExampleObject or ExampleObject[] ...
This should handle your issue, but a better API design would be having 2 different endpoints / URLs.

Related

Calling service activator vs bean methods in Spring Integration

There're few ways one can manipulate the message in Spring Integration. One way is calling a bean's method inside <int:enricher> that will return an object and assign it to the given name, e.g:
<!-- calls getKey method of IdGenerator bean which returns String with some value -->
<int:enricher input-channel="a.channel" output-channel="b.channel" id="preTranslator">
<int:header name="Key" expression="#IdGenerator.getId(payload)"/>
</int:enricher>
Same can be utilized in filtering:
int:filter discard-channel="d.channel" input-channel="b.channel" output-channel="c.channel"
expression="#Cache.hasKey(headers.Key) == false"/>
On the other hand I can call the <int:service-activator> on a class implementing MessageProcessor interface. It would take the original message and return a copy with a new header field. That requires my class's method to always build a new message with MessageBuilder though.
Currently I use the first way for simple field enrichment and service-activator for requesting data from DB/external services. What's the right way of picking the correct approach?
First of all, the <filter> doesn't change message at all. The given name should be read as header, looking to your case.
The <service-activator> always return a new message. Yes, you can populate new headers there as well and right you have to use MessageBuilder.
It is fully unclear what is your problem. If you can achieve the solution with expressions in the config, so be that. But if you do something with the message in the code and would like to add/edit/remove headers you use MessageBuilder.
That's really fine. I think you should just read more documentations and right more code in your application.
Eventually you will find the most convenient style for yourself. Fro example I end up once with expressions and Groovy scripts. No Java code at all. But right now I prefer Spring Integration Java DSL, because it is much faster, cleaner, fluent and lets get rid of any other configs like XML or Groovy. Everything is Java now and that MessageBuilder is still on the horse!

Which is better: returning a Response object or an Object representing the rest resource?

In some books, the rest APIs generally return a Response object which wraps some other objects representing payload, status, etc.
On the other hand many of the APIs that I have seen and written return a POJO (or call it a DTO) as JSON which is the consumed by the client.
This may be opinion based, but I would like to know which is better of the two to use on high scalability environment where some request result in success and others in failure/data not returned.
I would like to know if there is an accepted better practice. This will help me designing some APIs and put things in perspective before my team. But I am ok with this question being closed if 'better of the two' is too much opinion based.
Thanks.
Update:
The two rest APIs would look like this. Avoiding code like #Path, #Get, #PathParam, #Produces etc
public Response myCustomerObject(int id){...}
This returns a Customer object wrapped inside the Response object. Response could be error as well.
And the approach below will return the Customer entity directly:
public Customer myCustomerObject(int id){...}
I would vote for an API which gives you a Response object. This allows you to control the response completely within your code and it is clear what is going into response. And in cases where you want to write a Response which cannot easily be represented by a POJO you are not forced to use unintuitive workarounds.
Returning a Object from a rest handler method which is then transformed into a response is too much framework magic for my taste.
Worst - imho - is the practice to return a String from the rest handler method which is then interpreted as a template reference (e.g. the path to a JSP resource) which is then written to the response. Again way too much magic.
I prefer returning custom data objects instead if response objects. The whole point of the annotation based frameworks is to abstract away the http aspects from the application logic. Instead of managing response codes and entities, application developers return model objects and throw custom exceptions that can be mapped to http codes in a mapper. It's less control but IMHO it's way easier to rapidly develop an api.
The one returning response object contains your data is getting legacy of request/response services like SOAP and HTTP, but REST services build on concept of resources not request/response so I prefer to use objects represents your actual resources without wrapper, how could rest service represents your resources direct on response object for ex. if you are calling resource like car:
http://localhost/car GET for list of cars
http://localhost/car/1 GET for getting car with id 1
how to represent this in response object ?

Different URL-selected views for one controller method in Play framework 2.3

Play, I understand, seperates answers to a request in two layers: The controller method puts all the data together, the view actually creates the output.
I have a function "get customer list". The controller creates, say, a List. Now, what I want is to have two outputs of this controller's result:
1) I want the usual HTML output, so a controller which prints
...<table><tr><th>Name</th>...</tr>
<tr><td>Smith</td>...</tr>
...
</table>...
2) From the same List, I would also create a JSON (or CSV or XML) file containing the customer data as JSON information.
From how I understand Play, it should be possible to obtain this by putting another view renderer at the end of the controller. I would have two URLs, say
/customer/list.html
and
/customer/list.json
which return the two differently formatted results but which use the same controller (which btw. is implemented in Java).
Can this be done? How can this be done? Or is my approach not sensible?
Best regards,
Dirk
I'm a bit reluctant to answer here since I'm unsure about the Play Java stuff, but you could take two approaches:
have a route specified for every format you support (differing on .json, .html etc)
parameterise the suffix and response differently in the action depending on it's value.
Suppose you support both HTML and JSON output (with HTML the default.) You could define a single route like this:
GET /customer/list$format<(\.(:?html|json))?> controllers.Application.renderMyList(format: String)
(Note: the .type suffix is optional, you could have /list.html or /list.json or just /list. Read up about regex dynamic route parameters here.)
Your action might look like this:
public static Result renderMyList(String format) {
List<Something> myList = getMyList();
if (format.equals(".json") {
Ok(convertToJson(myList));
} else {
Ok(views.html.myList(myList));
}
}
On the other hand you could explicitly define two routes pointing to the same action, with different fixed parameters:
GET /customer/list.html controllers.Application.renderMyList(format: String = ".html")
GET /customer/list.json controllers.Application.renderMyList(format: String = ".json")
But I think the first option is more succinct and generally nicer.
NB: I think for this kind of content-dependent stuff it's generally better to use content negotiation instead of different URLs. You can read up on that here.

Design for executing a "pipeline" of user-defined actions based on input

Scenario
A web service receives a request in the form of XML from some other system, based on the contents of this request the web service should perform an arbitrary number of user-definable tasks (such as storing the contents of the XML to a database, extracting certain values, making a call to some other service etc). The behaviour of the requesting system cannot be changed (e.g. to call different actions for different things).
Proposed Design
My proposed design would be to have an interface something like...
interface PipelineTask {
public void Run(String xml);
}
With implementations of this for each user action, for example...
public class LogToDatabaseTask implements PipelineTask {
public void Run(String xml) {
db.store(xml); // some call to database to store.
}
}
Then a database table containing rules (maybe as XPath expressions), and the class to invoke should those rules be satisfied by the received document. I'd then use reflection - or perhaps a factory(?) - to invoke the correct implementation and run it.
Question
To me, it sounds like there should be some kind of existing pattern to implement something like this which I've missed and can't find online anywhere. Would this kind of approach make sense - or is there some better, perhaps more flexible way of doing this?
As you already mentioned, a rule seems a good fit for this case. You can define a rule that takes facts related to the current state and provide the next action in the sequence. Below is a simple java rule method as example. You can also use a rules framework like drools. The response from the rule can be used with a factory or a strategy:
For example, consider the sequence of actions:
UPDATE_DB
EXTRACT_VALUES
INVOKE_XYZ_SERVICE
END
For every web service request check the rule after every step and execute actions until you receive a rule response with next action END. The rulerequest also contains the contents of input document:
public RuleResponse execute(RuleRequest request) {
//initialization and extraction code here
if(request.previousAction.equals("EXTRACT_VALUES") && ....) {
RuleResponse.nextAction = "INVOKE_XYZ_SERVICE".
}
return response;
}
I know that you tagged the question as Java, but actually you can reuse a lot of the MSDN logical model of the Pipes & filters design pattern. The article is very good and I've used already in Java modules.
First you can also read this about Pipeline_software - it helped me a lot with ideas.

Exception when serializing a stateless object with jackson Json

I have been using the jackson implementation of the json protocol in my own little project, and it has gone just fine a while now until I decided (for the first time) to serialize a stateless object.
I know that might sound weird, why would I want to send a stateless object? What I serialize is requests for a server, and this particular one conatins no fields, just code for an instruction on the server side. My model can take any ClientRequest implementation and call it's perform() method. I want it to work even though the request comes without fields.
Code looks like this:
public class GetWallInputsRequest implements ClientRequest<List<WallInput>>
{
#JsonCreator public GetWallInputsRequest()
{
}
#Override public ServerResponse<List<WallInput>> perform()
{
return new WallMessageResponse( Wall.WALL.getInputs() );
}
}
I get JsonMappingException: No serializer found for class GetWallInputsRequest.
Google does not help me, which makes me wonder if I'm just being stupid. Sadly I don't see a way out of this.
I solved it after a lot of brute force attempting different things. And by solved it I mean not figured it out but made it work. By adding the line:
#JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.NONE)
above the class declaration it seems to work out. Why this is necessary I don't know, but now It sends an empty json string instead of crashing.
The documentation says
Value that indicates that no access modifiers are auto-detectable: this can be used to explicitly disable auto-detection for specified types.
Since your class doesn't include any explicit notations to tell Jackson that there's a field or method to serialize, it determines that there is indeed nothing to look for. Without this, I presume, it's going to expect something, as suggested in the documentation quoted.
http://jackson.codehaus.org/1.9.0/javadoc/org/codehaus/jackson/annotate/JsonAutoDetect.Visibility.html

Categories