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?
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
When we develop using MVC pattern it happens to need to having additional methods that could achieve basic operations on our models.
An example is an agregate getter that return the total count of the user records on the persistence base.
int getUsersCount();
Where is the best place to put such of those methods? In the model? In the controller?
Is there any difference between specific SDK/languages?
Java EE
Android
Laravel
vanilla PHP
...
Thanks.
I found this article that discuss about it: here it is a overview comparison between Purist OOP and Anemic Domain Model .
The overview basically explains that there are two big difference in the way you can implement a MVC design pattern.
The first way is about concetrate the methods, like the aggregate getter in this case, in a model related controller class.
For example, in Android, when we persist models in local or remote database, or we have to serialize it, or to marshall it, we tend to create those kind of ModelController classes and have so an anemic MVC pattern with clean POJO models.
class User extends MySuperModel{
int id;
String username;
//getters and setters
}
class UserController{
User getUserById(int id);
int getUsersCount();
}
The other way, consists in concentrate all the methods in the model class itself, for example as in Laravel (where controllers are demand to mainly control the post-routing and pre-rendering of a view, but doesn't tends to have other methods and neither their easy to instantiate. In this case we have a controlled domain MVC, and the additional model related methods should be in the model class itself.
class User extends Eloquent\Model{
protected $fillable = ['id', 'username']
function getUserById($id);
function getUsersCount();
}
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
I have a web service layer that is written in Java/Jersey, and it serves JSON.
For the front-end of the application, I want to use Rails.
How should I go about building my models?
Should I do something like this?
response = api_client.get_user(123)
User user = User.new(response)
What is the best approach to mapping the JSON to the Ruby object?
What options do I have? Since this is a critical part, I want to know my options, because performance is a factor. This, along with mapping JSON to a Ruby object and going from Ruby object => JSON, is a common occurance in the application.
Would I still be able to make use of validations? Or wouldn't it make sense since I would have validation duplicated on the front-end and the service layer?
Models in Rails do not have to do database operation, they are just normal classes. Normally they are imbued with ActiveRecord magic when you subclass them from ActiveRecord::Base.
You can use a gem such as Virtus that will give you models with attributes. And for validations you can go with Vanguard. If you want something close to ActiveRecord but without the database and are running Rails 3+ you can also include ActiveModel into your model to get attributes and validations as well as have them working in forms. See Yehuda Katz's post for details on that.
In your case it will depend on the data you will consume. If all the datasources have the same basic format for example you could create your own base class to keep all the logic that you want to share across the individual classes (inheritance).
If you have a few different types of data coming in you could create modules to encapsulate behavior for the different types and include the models you need in the appropriate classes (composition).
Generally though you probably want to end up with one class per resource in the remote API that maps 1-to-1 with whatever domain logic you have. You can do this in many different ways, but following the method naming used by ActiveRecord might be a good idea, both since you learn ActiveRecord while building your class structure and it will help other Rails developers later if your API looks and works like ActiveRecords.
Think about it in terms of what you want to be able to do to an object (this is where TDD comes in). You want to be able to fetch a collection Model.all, a specific element Model.find(identifier), push a changed element to the remote service updated_model.save and so on.
What the actual logic on the inside of these methods will have to be will depend on the remote service. But you will probably want each model class to hold a url to it's resource endpoint and you will defiantly want to keep the logic in your models. So instead of:
response = api_client.get_user(123)
User user = User.new(response)
you will do
class User
...
def find id
#api_client.get_user(id)
end
...
end
User.find(123)
or more probably
class ApiClient
...
protected
def self.uri resource_uri
#uri = resource_uri
end
def get id
# basically whatever code you envisioned for api_client.get_user
end
...
end
class User < ApiClient
uri 'http://path.to.remote/resource.json'
...
def find id
get(id)
end
...
end
User.find(123)
Basic principles: Collect all the shared logic in a class (ApiClient). Subclass that on a per resource basis (User). Keep all the logic in your models, no other part of your system should have to know if it's a DB backed app or if you are using an external REST API. Best of all is if you can keep the integration logic completely in the base class. That way you have only one place to update if the external datasource changes.
As for going the other way, Rails have several good methods to convert objects to JSON. From the to_json method to using a gem such as RABL to have actual views for your JSON objects.
You can get validations by using part of the ActiveRecord modules. As of Rails 4 this is a module called ActiveModel, but you can do it in Rails 3 and there are several tutorials for it online, not least of all a RailsCast.
Performance will not be a problem except what you can incur when calling a remote service, if the network is slow you will be to. Some of that could probably be helped with caching (see another answer by me for details) but that is also dependent on the data you are using.
Hope that put you on the right track. And if you want a more thorough grounding in how to design these kind of structures you should pick up a book on the subject, for example Practical Object-Oriented Design in Ruby: An Agile Primer by Sandi Metz.
In my java program, I had a book class and a library class.
The library stores the book object in an array list and then I display it on the screen.
I can add the book and remove the books using functions.
I also use AbstractJtableModel for adding and removing the books.
But now I want to use a database, MySQL, instead of an array list.
How should I change my program?
well, you need to write the whole application :)
you need to create a db, with at least one table, you need to add mysql jdbc library to classpath and using jdbc you can insert/select/update/delete data from DB.
Alternatively, you need to add jdbc and use ORM framework like Hibernate, but depending on your Java knowledge this way can be harder (but easier to maintain in future, if you create big application). Here you can download simple hibernate application, which does CRUD operations with Honey :), you can extract interface similar to suggested by Javid Jamae from TestExample class, and exchange Honey class with Book according to your needs
You might consider using the Data Access Object (DAO) pattern. Just do a Google search and you'll find tons of articles on the topic. Essentially, you'll create a LibraryDao interface with methods like:
public interface LibraryDao {
public void storeLibrary(Library library)
public Library loadLibrary(long id)
public List<Library> searchByTitle(String title)
//...
}
You can implement this interface with straight SQL, or you can use an Object Relational Mapping (ORM) tool to implement it. I highly recommend reading up on Hibernate and the JPA specification.
Abstract the retrieval and storage of the books into a class by itself - you don't want that persistence logic intermingled with your business logic. I'd suggest creating an interface called something like "BookStorageDAO" and then you can have various implementations of that interface. One implementation may be to store the books in an ArrayList while another may be to store the books in a Database.
In this way, you can utilize the interface in your business logic and swap out the implementation at any time.
You would still use the ArrayList in your GUI to persist and display the data. The difference would be you need logic to save and load that ArrayList from a database so that the data is stored even after the program ends.
Side note, extends DefaultTableModel as opposed to AbstractJtabelModel. It completes some of the methods for you.
You don't need a DAO per se, but those answers aren't wrong.
Separation of Concern
What you need to do is separate your application based on concern, which is a pattern called separation of concern. It's a leak to have concerns overlap, so to combat this, you would separate your application into layers, or a stack, based on concern. A typical stack might be include:
Data Access Layer (read/write data)
Service Layer (isolated business logic)
Controller (Link between view and model)
Presentation (UI)
etc., but this will only partly solve your problem.
Program To The Interface
You also (as the others have mentioned) need to abstract your code, which will allow you to make use of dependency injection. This is extremely easy to implement. All you have to do is program to the interface:
public interface PersonService {
public List<Person> getAllPersons();
public Person getById(String uuid);
}
So your application would look like this:
public class PersonApp {
private final PersonService personService;
public PersonApp(PersonService personService) {
this.personService = personService;
}
}
Why is this better?
You have defined the contract for interacting with the Person model in the interface, and your application adheres to this contract without having any exposure to the implementation details. This means that you can implement the PersonService using Hibernate, then later decide you want to use JPA, or maybe you use straight JDBC, or Spring, etc. etc., and even though you have to refactor the implementation code, your application code stays the same. All you have to do is put the new implementation on the classpath and locate it (tip: the Service Locator pattern would work well for that).