So, I'm coming up to speed on Jersey and have a "best practice" question. How strict should keep the resources self contained in one file. Should one resource class reference another class if needed?
An example:
I have a Person resource and an Appointment Resource. (ie: /Person/1 & /appointment/12345). I can also do something like /Person/1/Appointments to list all the appointments for person 1.
So, my question is should I implement a method getPersonAppointments() in the Person Resource class, or just someone get a reference to the Appointment resource class and call that method, keeping all the methods which return "Appointments" together.
I don't know that there is a right or a wrong way.
Since an appointment has multiple people, and a person has multiple appointments, the situation is symmetric and you have to pierce the barrier between the Persons and the Appointments.
Your REST API should simplify access to resources. One of the principles of REST is the idea of "Hypermedia as the Engine of Application State," which prefers to direct clients to related resources by their URIs so that the client doesn't need to know about how to construct URIs to certain resources a priori.
More information on that here: http://en.wikipedia.org/wiki/HATEOAS
The request to /person/1 should return information about that person, including a collection of appointment URIs. The client can then request any of those URIs to get information about each of those appointments. Implementing /person/1/appointments is redundant.
In your scenario I would put the logic for loading the appointments for person in one Resource and make it accessible from another Resource (in other words delegating the resource, what I'm assuming you doing already). The actual logic is stored in AppointmentService, so you can use it with your getPersonAppointments().
This way you can call it:
/person/1/appointments
/appointments?personId=1
Both resulting into same Response.
This is maybe not the best practise, but the logic is in one place and makes it more readable and reusable.
#Path("person")
public class PersonResource {
#GET
#Path("{personId: [0-9]+}/appointments")
public AppointmentsResource loadAppointmentsForPerson(#PathParam("personId") Long personId) {
return new AppointmentsResource(personId);
}
}
#Path("apointments")
class AppointmentResource {
private AppointmentService service;
private Long personId;
public AppointmentResource() {
}
public AppointmentResource(Long personId) {
this.personId = personId;
}
#GET
public Response loadAppointmentsForPerson(#QueryParam("personId") Long personId) {
Long personIdToUse = null;
if (this.personId != null) {
personIdToUse = this.personId;
} else if (personId != null) {
personIdToUse = personId;
} else {
//no input, bad request
}
List<Appointment> appointments = service.getPersonAppointments(personIdToUse)
//create your response from appointments
}
}
Of course in your AppointmentResource, you'll then have another stuff, like loading the appointment by specific ID.
Related
Let's pretend a RESTful service receives a PATCH request to update one or more fields of an entity that might have tens of fields.
#Entity
public class SomeEntity {
#Id
#GeneratedValue
private Long id;
// many other fields
}
One dirty way to patch the corresponding entity is to write something like this:
SomeEntity patch = deserialize(json);
SomeEntity existing = findById(patch.getId());
if (existing != null)
{
if (patch.getField1() != null)
{
existing.setField1(patch.getField1());
}
if (patch.getField2() != null)
{
existing.setField2(patch.getField2());
}
if (patch.getField3() != null)
{
existing.setField3(patch.getField3());
}
}
But this is insane! And if I want to patch 1 to many & other associations of the entity the insanity could even become hazardous!
Is there a sane an elegant way to achieve this task?
Modify the getter's of SomeEntity and apply check, if any value is blank or null just return the corresponding entity object value.
class SomeEntity {
transient SomeEntity existing;
private String name;
public String getName(){
if((name!=null&&name.length()>0)||existing==null){
return name;
}
return existing.getName();
}
}
You can send an array containing the name of the fields you are going to patch. Then, in the server side, by reflection or any field mapping, set each field to the entity. I have already implemented that and it works, thought my best advice is this:
Don't publish an endpoint to perform a "generic" PATCH (modification), but one that performs a specific operation. For instance, if you want to modify an employee's address, publish an endpoint like:
PUT /employees/3/move
that expects a JSON with the new address {"address" : "new address"}.
Instead of reinventing the wheel by writing the logic yourself, why don't you use a mapping library like Dozer? You want to use the 'map-null' mapping property: http://dozer.sourceforge.net/documentation/exclude.html
EDIT I am not sure whether or not it would be possible to map a class onto itself. You could use an intermediary DTO, though.
For example I have a bean
public class Order
{
int orderID;
String name;
}
And I have a POST operation
#ApiOperation(value = "Insert a new order", response = Order.class)
#RequestMapping(value = "/addOrder", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
#ResponseBody
public Order addOrder(#Valid #RequestBody Order order)
{
//Set random id here
order.id = 'xxxxx';
Order o = orderService.insertOrder(order);
return o;
}
And in Swagger I have the following:
So my question is, how do I hide id on POST but show ID on GET?
Or should I add a description saying that even if you choose to add an ID it wont do anything and just return my random id? Just like in Kubernetes (uid)
And properties like read-only in #ApiModelProperty will solve anything?
A simple approach is to split your bean in two - one for creating a new object, and another one which extends that for data about an existing object.
e.g.
public class IncompleteOrder {
String name;
}
public class ExistingOrder extends IncompleteOrder {
int id;
}
Then have your POST method take an object of IncompleteOrder and return one of ExistingOrder. I'd also delegrate responsibility for assigning a random order id to the underlying service...
public ExistingOrder addOrder(#Valid #RequestBody IncompleteOrder order) {
ExistingOrder o = orderService.insertOrder(order);
return o;
}
The same thing could be achieved by having two completely separate classes with no inheritance relationship, which would probably be appropriate if there was a significant divergence between the information needed to create a new order from the information which is on an existing order.
An alternative is to ask what the id is actually for - why are your clients getting integer id's for anything? Ideally, if they want any information about the order they should be querying the API for the resource, and to do that they need the URI of the order rather than the integer id. So external services communicating about an order should be passing the URIs back and forth rather than ids. Perhaps you could encourage your clients to communicate with each via the URI you return in the Location header from your POST request? Then you could do away with exposing the id on your response and have a purely symmetric request / response body.
OK, so I have an interesting problem. I am using java/maven/spring-boot/cassandra... and I am trying to create a dynamic instantiation of the Mapper setup they use.
I.E.
//Users.java
import com.datastax.driver.mapping.annotations.Table;
#Table(keyspace="mykeyspace", name="users")
public class Users {
#PartitionKey
public UUID id;
//...
}
Now, in order to use this I would have to explicitly say ...
Users user = (DB).mapper(Users.class);
obviously replacing (DB) with my db class.
Which is a great model, but I am running into the problem of code repetition. My Cassandra database has 2 keyspaces, both keyspaces have the exact same tables with the exact same columns in the tables, (this is not my choice, this is an absolute must have according to my company). So when I need to access one or the other based on a form submission it becomes a mess of duplicated code, example:
//myWebController.java
import ...;
#RestController
public class MyRestController {
#RequestMapping(value="/orders", method=RequestMethod.POST)
public string getOrders(...) {
if(Objects.equals(client, "first_client_name") {
//do all the things to get first keyspace objects like....
FirstClientUsers users = (db).Mapper(FirstClientUsers.class);
//...
} else if(Objects.equals(client, "second_client_name") {
SecondClientUsers users = (db).Mapper(SecondClientUsers.class);
//....
}
return "";
}
I have been trying to use methods like...
Class cls = Class.forName(STRING_INPUT_VARIABLE_HERE);
and that works ok for base classes but when trying to use the Accessor stuff it no longer works because Accessors have to be interfaces, so when you do Class cls, it is no longer an interface.
I am trying to find any other solution on how to dynamically have this work and not have to have duplicate code for every possible client. Each client will have it's own namespace in Cassandra, with the exact same tables as all other ones.
I cannot change the database model, this is a must according to the company.
With PHP this is extremely simple since it doesn't care about typecasting as much, I can easily do...
function getData($name) {
$className = $name . 'Accessor';
$class = new $className();
}
and poof I have a dynamic class, but the problem I am running into is the Type specification where I have to explicitly say...
FirstClientUsers users = new FirstClientUsers();
//or even
FirstClientUsers users = Class.forName("FirstClientUsers");
I hope this is making sense, I can't imagine that I am the first person to have this problem, but I can't find any solutions online. So I am really hoping that someone knows how I can get this accomplished without duplicating the exact same logic for every single keyspace we have. It makes the code not maintainable and unnecessarily long.
Thank you in advance for any help you can offer.
Do not specify the keyspace in your model classes, and instead, use the so-called "session per keyspace" pattern.
Your model class would look like this (note that the keyspace is left undefined):
#Table(name = "users")
public class Users {
#PartitionKey
public UUID id;
//...
}
Your initialization code would have something like this:
Map<String, Mapper<Users>> mappers = new ConcurrentHashMap<String, Mapper<Users>>();
Cluster cluster = ...;
Session firstClientSession = cluster.connect("keyspace_first_client");
Session secondClientSession = cluster.connect("keyspace_second_client");
MappingManager firstClientManager = new MappingManager(firstClientSession);
MappingManager secondClientManager = new MappingManager(secondClientSession);
mappers.put("first_client", firstClientManager.mapper(Users.class));
mappers.put("second_client", secondClientManager.mapper(Users.class));
// etc. for all clients
You would then store the mappers object and make it available through dependency injection to other components in your application.
Finally, your REST service would look like this:
import ...
#RestController
public class MyRestController {
#javax.inject.Inject
private Map<String, Mapper<Users>> mappers;
#RequestMapping(value = "/orders", method = RequestMethod.POST)
public string getOrders(...) {
Mapper<Users> usersMapper = getUsersMapperForClient(client);
// process the request with the right client's mapper
}
private Mapper<Users> getUsersMapperForClient(String client) {
if (mappers.containsKey(client))
return mappers.get(client);
throw new RuntimeException("Unknown client: " + client);
}
}
Note how the mappers object is injected.
Small nit: I would name your class User in the singular instead of Users (in the plural).
I am working on an application which has REST endpoints and for a Get-By-ID service, I am populating a resource (basically a POJO) by collecting data from the persistent store. Now, before sending the response back, I have to populate the HREF in the POJO resource. I want to do it in a generic way so that various other REST services (search etc.) can use it. I want to do this HREF population at a common place for reusability purpose. In a nutshell, my resource POJO can go through various massaging layers to have different state changed and finally sent back to the consumer.
Resource POJO --> Massager 1 --> Massager 2 --> Final Massaged POJO
Could someone help me to figure out a design pattern that can fit my problem.
I thought of Decorator pattern, but somehow it does not sail my ship.
~ NN
You could adapt Chain Of Responsability to your needs. Instead of having a series of processing objects which pass your POJO from one to another in case it cannot handle it, you could process your POJO and then pass it further.
abstract class Messager{
private Messager nextMessager;
void setNextMessager(Messager messager){
this.nextMessager = messager;
}
Messager getNextMessager(){
return this.nextMessager;
}
abstract void handle(Pojo pojo);
}
class FooMessager extends Messager{
void handle(Pojo pojo){
//operate on your pojo
if(pojo.getHref == null){
pojo.setHref("broken");
}
if(this.getNextMessager() != null){
this.getNextMessager().handle(pojo);
}
}
}
class BarMessager{
void handle(Pojo pojo){
//operate on your pojo
if(pojo.getHref().contains("broken")){
pojo.setHref(pojo.getHref().replace("broken","fixed"));
}
if(this.getNextMessager() != null){
this.getNextMessager().handle(pojo);
}
}
}
class Pojo{
private String href;
public Pojo() {
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
class Test{
public static void main(String[] args) {
Pojo pojo = new Pojo();
pojo.setHref(null);
Messager foo = new FooMessager();
Messager bar = new BarMessager();
foo.setNextMessager(bar);
foo.handle();
}
}
Even if the previous answers are good and does solve it, I want to propose you additional way if you want to go further. The communication between objects is very common, so a lot of concepts are out there and you can choose the one that fits best for your needs.
The Command pattern can help you with the encapsulation of a request as an object in
collecting data from the persistent store
It'll allow you to parameterize clients with queue or log requests.
The Mediator pattern can define your communication between the Massager 1 --> Massager 2 classes. By doing this it'll encapsulate your objects interaction. Also it promotes loose coupling by keeping objects from referring to each other explicitly, and it'll let you vary their interaction independently.
If you'll deal with how to notify change to Massager 1 --> Massager 2 classes
my resource POJO can go through various massaging layers to have different state changed
than the Observer pattern can define a dependency between your objects so that when one object changes state, all its dependents are notified and updated automatically.
I am working on creating a RESTful API for a project. I am facing a few problems trying to implement it with jersey:
My object model does not contain uri info obviously. e.g, lets say I have a Fruit class. Fruit object would have let's say a FruitName and a FruitColor. But in the response I also need to send a URI. How is this usually handled? Should I create a separate "FruitResource" that has a constructor which takes a "Fruit" and creates a full resource from it, including URI? I need URIs in the nested objects as well, e.g if I am returning a list of Child objects, I need each Child object to also have a URI, but I donlt want the URI to be part of the object model. What is the cleanest way to do this?
I want to have capability to return full and partial views of the same resource. Partial views would just have the name and the URI for example. How to get this done?
Right now what I have is a Service class that accepts the requests, which uses the DAO to create and return the objects as they are modelled from the DB, serialized to JSON using jackson.
There i a way to use JaxB class and you can pass Object Model to JaxB class and JaxB class generates URI.
The below is small prototype.
UserResource Class
#Path("/user")
public class UserResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{user-id}")
public UserJaxB getUser(#PathParam("user-id") String userId, #Context
HttpServletRequest request) {
// now XYZ is hard-coded value
String serviceEndpoint = request.getContextPath() + "/" + "user";
UserModel userModel = new UserModel(userId, "XYZ");
return new UserJaxB(serviceEndpoint,userModel);
}
}
User JAXB Class
#XmlRootElement
public class UserJaxB {
private String name;
private String id;
private String serviceEndpoint;
private String URI;
public UserJaxB(String serviceEndpoint, UserModel userModel) {
this.name = userModel.getName();
this.id = userModel.getId();
this.serviceEndpoint = serviceEndpoint;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getURI() {
return this.serviceEndpoint + "/" + id;
}
}
User Model Class
public class UserModel {
String name;
String id;
public UserModel(String name, String id) {
this.name = name;
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
I'm working on a project that supports both of those concerns: https://github.com/skyscreamer/yoga with more information at http://yoga.skyscreamer.org/, including a demo.
It replaces the JAX-RS (or Spring MVC) rendering mechanism with a custom built solution that's more in tune with the needs of a REST System.
For #1, we have an annotation that you have to apply to your Child pojo. JAX-RS's annotations are meant to map URLs to controllers not to the underlying object, so we needed a custom solution... but it's really just comes down to 1 additional annotation per pojo.
For #2, we have a URL based mechanism of specifying which additional information you want from a pojo or a pojo's children (and can be nested further).
I hope this helps.
1) I'm not aware of any Jersey or JAX-RS mechanism supporting this. Seems like a bad practice to have to add the URI to the constructor for each of your domain classes, though. You could create an aspect that would intercept the method and wrap the response in a new object - adding the URI of the resource in the wrapper (you could get the URIInfo via reflection from the interceptor). I've done this when building etag support so I don't have to add cache code to every response. I suppose you could also add something in the same aspect to handle the child URI issue...
You might also want have a look at these dicussions:
http://java.net/projects/jersey/lists/users/archive/2009-01/message/357
http://markmail.org/search/?q=list%3Anet.java.dev.jersey.users+brett.dargan%40gmail.com#query:list%3Anet.java.dev.jersey.users%20brett.dargan%40gmail.com+page:1+mid:7ln7wixfihfodngg+state:results
2) For building "lighter" response entities I typically have a BeanLite.class with just the properties I need for a summary and then a Bean.class extending it with more detail. You can add both to your ORM and provide an option to switch representations in your DAO.
Thanks for all your responses. Going through all the approaches you guys presented and after a little bit of research on my own, this is what I settled on:
1) I am adding uri as part of the object model. This seems to be the cleanest solution to me currently. The URI can be automatically populated whenever the object is created (using other properties of the object). Earlier I thought this is a bad idea, but I am not able to foresee any problems with this approach other than the extra field that will have to keep moving with the objects.
2) For supporting full/partial views, I am trying to use the #JsonView annotation. This seems to be a good approach.
Let me know if there are any other potential issues with this way of handling things.