We have a front-end service that uses a back-end service to get a list of Metric objects. We've written a Java ClientSDK for the back-end service to make life easier for development of client applications of that service.
We also expose a list of Metrics from the front-end service. For now, we're directly exposing and converting the back-end Metric objects to JSON.
My concern is that if changes are made to the back-end Metric object - say a developer adds a new secret ID field - we don't want to expose it from the front-end service.
We're also writing a clientSDK for the front-end service. We don't want to reference the Metric class from the back-end clientSDK, so the logical option is to define a similar Metric object in the front-end SDK.
I don't want to waste CPU cycles copying 1000's of Metrics from one class definition to another.
Is there a way to specify which fields I should expose from the back-end Metric to the front-end definition of Metric as I'm converting to JSON? Better yet, can I reference the front-end definition to the JSON converter as I ask it to marshal the back-end object?
We're using Jackson with the Spring rest framework for context, but I'd be happy to drop that in a heartbeat since marshaling objects via annotations seems to be the root cause of this problem.
Take a look at Jackson's JsonView construct.
I can see your example looking something like this:
class Views {
static class Client {}
static class Backend extends Client {}
}
public class Metric {
#JsonView(Views.Client.class) String metricName;
#JsonView(Views.Client.class) String count;
#JsonView(Views.Backend.class) String secretKey;
}
The #JsonView annotation is supported on Spring #ResponseBody annotated methods as of Spring 4.1.
As Nicholas Hausschild has suggested you can achieve this by annotations with your marshalling/unmarshalling framework.
However you can simply use inheritance and casting like this:
class SomeSuperClass {
String exposeThis;
String exposeThat;
// getters and setters...
}
class SomeSubClass extends SomeSuperClass {
String doNotExposeThis;
// getters and setters...
}
This way you can cast to the super class when returning an object to the JSON parser, and at the same time use the subclass internally to carry additional information which you don't really want to expose.
Another possibility is the use of Mixins, so you can define different scenarios without touching the original DTO.
I myself use a library I wrote to achieve this dynamically:
https://github.com/Antibrumm/jackson-antpathfilter
This works well for not too deep graphs, else someone wrote another approach in a similar way here which seems more performant for these scenarios, but behaves a bit different.
https://github.com/krishna81m/jackson-nested-prop-filter
Related
I've got a pretty general question.
For my work I have to implement a demonstrator application using MongoDB, Java and JavaFX (and yWorks). So since I - unfortunately - have to work alone on this and there is not a huge amount of know-how in our company, all I did was studying and learning these technologies for myself.
And since we don't want to have a server application there is only MongoDB as a service and the client working on the data. (This is okay, since its only a demonstrator). But im kind of confused.
Implementing pojo classes to store and load from the database and implementing gui model classes with the exact same properties but using "SimpleStringProperty" by JavaFX led to the - in my opinion - weird fact, that i have two semantically identic model classes that I have to implement some kind of Observer/Observable-Pattern to propagate changes from the ViewModels to the POJOS and vice versa.
There must be a more elegant way to do this, right?
Any ideas on this?
Some visualisation:
Analyse
Just the analyse, skip to the proposition if you dont want details
The question to duplicate or not class model definition is an architectural choice, but theses 2 solutions are possible and acceptable:
Use your model bean in controller and Screen
Duplicate all your classes with helpers method from/to for the conversions.
Since the duplication is possible but trivial, I will only describe how to use directly models, there are still another 2 solutions:
1.1 Just manually bind your attributes (the simpler but not the more elegant)
Create Observable SimpleStringProperty ... on the fly when binding read-only, or use Helpers to add listener on screen observable to call regular setter when a value is modifiable
1.2. Make your data framework use getters/setters and not fields: in most case you can configure it (that's the case for hibernate) So if mongodb can serialize/deserialize objects using method and not field, It will be possible
I suppose here that you use standard javaFX bean with 3 accessor on each attributes: get,set,property.
Proposition
Sorry for this big intro, here is a proposed solution using Jackson.
First It is aparently possible to use mongodb with Jackson:Efficient POJO mapping to/from Java Mongo DBObject using Jackson
Then here is an example code of javaFX Bean with jackson:
#JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.PUBLIC_ONLY, setterVisibility = Visibility.PUBLIC_ONLY)
public class MyBean {
private final StringProperty label = new SimpleStringProperty();
public final StringProperty labelProperty() {
return this.label;
}
public final String getLabel() {
return this.labelProperty().get();
}
public final void setLabel(final String label) {
this.labelProperty().set(label);
}
}
You are using morphia, you have to check if this is possible.
Side note:
I'm asking a similar question about non duplication of object on the link below (I am in a 3 tier not 2 tier, but still duplication problem), the usual solution for instance is still the duplication:
https://softwareengineering.stackexchange.com/questions/367768/how-to-avoid-dto-on-a-client-server-application?noredirect=1#comment804724_367768
I'm trying to learn Spring Boot by implementing a simple REST API.
My understanding was that if I need to transfer an object over the wire, that object should implement Serializable.
In many examples on the net though, including official ones, domain classes that need to be transferred from server to client (or vice-versa) do not to implement Serializable.
For instance: https://spring.io/guides/gs/rest-service/
But in some cases, they do:
For instance: https://github.com/szerhusenBC/jwt-spring-security-demo/blob/master/src/main/java/org/zerhusen/security/JwtAuthenticationRequest.java
Is there a general rule of thumb on when to implement Serializable?
To update this, advice about Serializable has changed, the recommendation currently seems to be Don’t use Serializable for anything.
Using the Java serialization API means you need something in Java on the other side of the wire to deserialize the objects, so you have to control the code that deserializes as well as the code that serializes.
This typically isn't relevant for REST applications, consuming the application response is the business of someone else's code, usually outside your organization. When building a REST application it's normal to try to avoid imposing limitations on what is consuming it, picking a format that is more technology-agnostic and broadly available.
Some reasons for having an object implement java.io.Serializable would be:
so you can put it in an HttpSession
so you can pass it across a network between parts of a distributed application
so you can save it to the file system and restore it later (for instance, you could make the contents of a queue serializable and have the queue contents saved when the application shuts down, reading from the save location when the application starts to restore the queue to its state on shutdown).
In all these cases, you serialize so you can save something to a filesystem or send it across a network.
There are many ways to serialize an object. Java's object serialization is just one of them. From the official documentation:
To serialize an object means to convert its state to a byte stream
REST APIs usually send and receive JSON or XML. In that case serializing an object means converting its state to a String.
There is no direct connection between "sending an object over the wire" and implementing Serializable. The technologies you use dictate whether or not Serializable has to be implemented.
The specific examples you have mentioned do not transfer objects over the wire. From the example links I see that the controller methods return a domain object with ResponseBody annotation. Just because the return type of the method is the domain object it is not necessary that the whole object is being sent to the client. One of the handler method in Spring mvc framework internally intercepts the invocation and determines that the method return type does not translate to direct ModelAndView object. RequestResponseBoodyMethodProcessor which handles the return value of such annotated methods and uses one of the message converters to write the return object to the http response body. In the case the message converter used would be MappingJackson2HttpMessageConverter. So if are to follow the same coding style you are not required to implement Serializable for your domain objects.
Have a look at this link for the Http message converters provided by default from spring. The list is quiet extensive however not exhaustive and if requirements arise you can implement your own custom message converter to user as-well.
that's a good question when to implement Serializable interface.
these links can provides some useful contents:
Serializing java.io.Serializable instance into JSON with Spring and Jackson JSON
When and why JPA entities should implement the Serializable interface?
I sometimes wonder about this, and I think
Because Java is a open source language, and more libraries providered by third party. for tells who will serialize and deserialize the object, the java offical declare a constract interface, makes transfer easy and safety throught different library.
It's just a constract, most third-party libraries can serialize/deserialize when checking implement this constract. and jackson's jar library is not use it.
So you can deem if you use serialize/deserialize object data in your own system, and simple process, likes just serialize and response it(jackson in spring MVC), you needn't to implements it.
but if you used in other jar library, likes saving in HttpSession, or other third-party componens/library, you should(or have to) implement Serializable, otherwise the libraries will throw a exception to tell you the constract interfaced which it knows is not provide.
But they said it's a good habit and best properties that to implement the Serializable when serialize a custom class. :)
you should serialize if you are using caching for database operations.Usually the third party cache providers like (hazle cast, Jboss cache etc..) internally serialize/ de serialise objects.In that case model classes should implement Serializable to facilitate caching.
In a project I am currently working on, HAL support through the REST API is obtained by extending Springs org.springframework.hateoas.ResourceSupport, in order that links can be added to an object.
A quick example:
public class MyDataRepresentation extends ResourceSupport {
private String name;
}
Now in the web layer, I can add links in to the representation:
MyDataRepresentation myData = someService.getTheData();
myData.add(new Link(someUrl, someRel));
All well and good.
The problem is that I would rather re-use the domain object (MyData) directly, and not create a separate class in the web representation layer in order to accomplish this. The reason for this, is that my application in this particular case is simple enough that the domain object can be used directly, and I wish to avoid having mapping logic to translate to/from the web layer, either hand-coded or using a mapping tool. A further argument against mapping logic is that business logic often creeps into mapping logic, making the business logic even harder to follow.
So here is the domain class:
public class MyData {
private String name;
}
Unfortunately this does not give me anywhere to attach my HAL links to.
So my question is, is there a HAL framework for Java, that lets me directly re-use domain objects in the web layer without resorting to using 'extends' and forcing my down the route of web/domain mapping logic?
Some other way of using HAL support in Spring that lets me do this? What about HAL support in Jersey, is that less obtrusive?
I'm using web services and I want to step it up a notch. I'm using Axis2 with JAX-WS. I'm thinking of transfering objects instead of String[]. After I googled a bit, I found that JAXB is the right support to do this.
However, everytime I want to add a modelclass that needs to be transferred, I need to do a lot of work (to shut up about all the annotations where I can make mistakes). So I thought it would be easier to abstract this a bit.
I was thinking of creating web services using the Object type. I can then use methods as addObject(Object object), removeObject(Object object), retrieveObject(). This means my server needs to handle incomming objects. If I then add a new model class, I just need to catch it at server end. My client will need to include the model classes causing some redundancy but I'm OK with that. I have the feeling that Java cannot support my idea at this momemnt. At least JAX-WS & JAXB technologies.
Can you guys tell me if I'm right or wrong about this, if this is a good idea or not and if so, maybe point me into the right direction on how to fix this (even if it means using another technology)
Thanks in advance!
Your client won't need a model type, but you will have to serialize and deserialize your data when you send messages from your server to your client. I'm not sure if JAX-WS is different from JAX-RS, but if they are the same, then you can add annotations that mark whether or not you want to produce/consume json or xml.
Once you serialize your model to json, your client will have no problem reading your data.
Also, yest you can use object when creating request and response objects. In a webservice that I recently wrote I created a service response class similar to this
public class Response
{
private Object data;
private boolean success;
public Response()
{
super();
}
//write getters and setters here
}
I think that I'm using the Object class in a similar fashion to what you have in mind.
I definitely recommend you JAX-RS (implementing JAXB), in particular using the Jersey framework. It's usage is simple and allow you to marshall and unmarshall business objects.
Look at this Jersey Example
Hope it helps!
I was wondering if is it possible to force the rest framework in java to return the actual implementation of some class instead of information that is only visible in the abstract class.
So I have a method that looks like
#GET
#Path("/}")
public Model getModel() {
return (Car) system.getCar();
}
So I would like that when ever someones hits this path to what is returned is the information about the CAR and not just what is contained in the model. Is it possible to force this behavior with some annotations?
PS The example above is just for demonstration. The actually reason is that I have a class that has a parameter of the abstract class and I would like to see the information in the xml about the concrete implementation so that I know what type it is.
Thanks for assistance.
cheers
EDIT
To tell you truth I have no idea what is the implemenation. But maybe this artical about what I use can help you http://docs.codehaus.org/display/TYNAMO/tapestry-resteasy+guide
I tested this in my REST project, it works without any extra work. I am using RestEasy framework to implement REST webservices. I checked this for XML as well as JSON datatype. For JSON serialization I am using jackson library.
The REST implementation serializes an actual concrete instance of a class (not an abstract class, since you cant have an instance of an abstract class anyway) into the requested content type, for eg, JSON or XML.
What gets serialized is the domain object's fields based on their mappings.
You can control what fields of the domain object gets serialized, or you can create a custom POJO with only fields that you want to send in the response.
It is not working on my JSON (with JACKSON), and I think it indeed should not work.
If your API provides a Model then it should not return Car fields. The executor of the API might not be able to parse the returned Car fields, since expected a Model.
This would be kind of up-casting which is generally shows a bad design. IMHO.
I liked the question though :)