I'm developing (another) java web framework for personal use, and in addition to that I also want to develop somekind of persistence framework.
I have already developed and engine that in order to access the table, you must only extend a class and create your fields with the same type and name of those in the table. Ex:
private int id;
private String nome;
So you only need now to build the query and execute. The engine put the values on the right fields.
Recently I've had a quite good experience with Django, wich in order to update, create and filter the table you just need to call .save(), .create(field1=field, field2=213) and, .filter(filterfield=value).
I want to build this to, but I am having some trouble, because the extending class would actually have to write more, fact that I don't want to force. I have had the idea to the extending class write an enum implementing an Interface. So the super class get those fields, along with a private HashMap (the key is the enum) and keep the values, so the client just calls:
String nome = Usuarios.get(Usuarios.fields.name);
To retrieve the value.
Usuarios.update(new Pair(Usuarios.fields.name, "José Leal"), new Pair(Usuarios.fields.sobrenome, "Domingues"));
To update and so on.
Anyone have a better idea? I also use velocity framework, so I would like my field to be accessible by its getter.
ps: I know the existence of hibernate and etc.
I would suggest that you not force users to extend one of your own classes for their model objects. This locks them out of extending their own classes, and makes them more vulnerable to API changes you might make later.
Seeing as javax.persistence already defines annotations that can be used for mapping properties to a database, I'd suggest instead that you let the users make POJOs for their model objects with annotated properties. That way, along with the other mentioned benefits, you're following an already established standard and thereby lowering the barrier to entry for your users.
Related
I'm (trying to :) using spring-boot-starter-data-rest in my spring boot app to quickly serve the model through true, fullblown, restFULL api. That works great.
Question 1 (Security):
The advantage of Spring JpaRepository is I don't need to code basic functions (save, findAll, etc). Is it possible to secure these auto-implemented methods without overriding all of them (wasting what Spring provided for me)? i.e.:
public interface BookRepository extends JpaRepository<Book, Long> {
#PreAuthorize("hasRole('ROLE_ADMIN')")
<S extends Book> Book save(Book book);
}
.
Question 2 (Security):
How to secure a JpaRepository to prevent updating items the loggeg-in user is not an owner?
i.e.: User is allowed to modify only his/her own properties.
i.e.2: User is allowed to modify/delete only the Posts he/she created.
Sample code is highly welcome here.
.
Question 3 (DTOs):
Some time ago I had an argue with a developer friend: He ensisted that there MUST be DTOs returned from Spring MVC controllers. Even if the DTO is 1-1 copy of the model object. Then I reserched, asked other guys and confirmed it: DTOs are required to divide/segregate the application layers.
How this relates to JpaRepositories? How to use DTOs with Spring auto serverd rest repos? Should I DTOs at all?
Thanks for your hints/answers in advance !
Question 1: Security
Some old docs mention:
[...] you expose a pre-defined set of operations to clients that are not under you control, it’s pretty much all or nothing until now. There’s seemingly no way to only expose read operations while hiding state changing operations entirely.
which implies that all methods are automatically inherited (also, as per standard java inheritance behavior).
As per the #PreAuhtorize docs, you can place the annotation also on a class / interface declaration.
So you could just have one basic interface extend JpaRepository
#NoRepositoryBean // tell Spring not create instances of this one
#PreAuthorize("hasRole('ROLE_ADMIN')") // all methods will inherit this behavior
interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {}
and then have all of your Repository's extend BaseRepository.
Question 2: Security
I'm going to be a little more general on this one.
In order to correctly regulate access to entities within your application and define what-can-see-what, you should always separate your project into different layers.
A good starting point would be:
layer-web (or presentation-layer): access to layer-business, no access to the db-layer. Can see DTO models but not DB models
layer-business (or business-layer): access to the db-layer but no access to the DAO
layer-db (or data-layer): convert DTO -> DB model. Persist objects and provide query results
In your case, I believe that the right thing to do, would be therefore to check the role in the layer-business, before the request even reaches the Repository class.
#Service
public interface BookService {
#PreAuthorize("hasRole('ROLE_ADMIN')")
ActionResult saveToDatabase(final BookDTO book);
}
or, as seen before
#Service
#PreAuthorize("hasRole('ROLE_ADMIN')")
public interface BookService {
ActionResult saveToDatabase(final BookDTO book);
}
Also, ensuring a user can modify only its own objects can be done in many ways.
Spring provides all necessary resources to do that, as this answer points out.
Or, if you are familiar with AOP you can implement your own logic.
E.g (dummyCode):
#Service
public interface BookService {
// custom annotation here
#RequireUserOwnership(allowAdmin = false)
ActionResult saveToDatabase(final BookDTO book);
}
And the check:
public class EnsureUserOwnershipInterceptor implements MethodInterceptor {
#Autowired
private AuthenticationService authenticationService;
#Override
public Object invoke(Invocation invocation) throws Throwable {
// 1. get the BookDTO argument from the invocation
// 2. get the current user from the auth service
// 3. ensure the owner ID and the current user ID match
// ...
}
}
Useful resources about AOP can be found here and here.
Question 3: DTO's and DB models
Should I DTOs at all?
Yes, yes you should. Even if your projects has only a few models and your are just programming for fun (deploying only on localhost, learning, ...).
The sooner you get into the habit of separating your models, the better it is.
Also, conceptually, one is an object coming from an unknown source, the other represents a table in your database.
How this relates to JpaRepositories?
How to use DTOs with Spring auto serverd rest repos?
Now that's the point! You can't put DTO's into #Repositorys. You are forced to convert one to another. At the same point you are also forced to verify that the conversion is valid.
You are basically ensuring that DTOs (dirty data) will not touch the database in any way, and you are placing a wall made of logical constraints between the database and the rest of the application.
Also I am aware of Spring integrating well with model-conversion frameworks.
So, what are the advantages of a multi-layer / modular web-application?
Applications can grow very quickly. Especially when you have many developers working on it. Some developers tend to look for the quickest solution and implement dirty tricks or change access modifiers to finish the job asap. You should force people to gain access to certain resources only through some explicitly defined channels.
The more rules you set from the beginning, the longer the correct programming pattern will be followed. I have seen banking application become a complete mess after less then a year. When a hotfix was required, changing some code would create two-three other bugs.
You may reach a point where the application is consuming too many OS resources. If you, let's say, have a module module-batch containing background-jobs for your application, it will be way easier to extract it and implement it into another application. If your module contains logic that queries the database, access any type of data, provides API for the front-end, ecc... you will be basically forced to export all your code into your new application. Refactoring will be a pain in the neck at that point.
Imagine you want to hire some database experts to analyze the queries your application does. With a well-defined and separated logic you can give them access only to the necessary modules instead of the whole application. The same applies to front-end freelancers ecc... I have lived this situation as well. The company wanted database experts to fix the queries done by the application but did not want them to have access to the whole code. At the end, they renounced to the database optimization because that would have exposed too much sensitive information externally.
And what are the advantages of DTO / DB model separation?
DTO's will not touch the database. This gives you more security against attacks coming from the outside
You can decide what goes on the other side. Your DTO's do not need to implement all the fields as the db model. Actually you can even have a DAO map to many DTO's or the other way around. There is lots of information that shouldn't reach the front-end, and with the DTO's you can easily do that.
DTO are in general liter than #Entity models. Whereas entities are mapped (e.g #OneToMany) to other entities, DTO's may just contain the id field of the mapped objects.
You do not want to have database objects hanging around for too long; and neither being passed around by methods of your application. Many framework commit database transactions at the end of each method, which means any involuntary change done onto the database entity may be committed into the db.
Personally, I believe that any respectful web-application should strongly separate layers, each with its responsibility and limited visibility to other layers.
Differentiation between database models and data transfer objects is also a good pattern to follow.
At the end this is only my opinion though; many argue that the DTO pattern is outdated and causes unnecessary code repetition any many argue that to much separation leans to difficulty in maintaining the code. So, you should always consult different sources and then apply what works best for you.
Also interesting:
SE: What is the point of using DTO (Data Transfer Objects)?
Lessons Learned: Don't Expose EF Entities to the Client Directly
Guice Tutorial – method interception (old but gold)
SO: Large Enterprise Java Application - Modularization
Microsoft Docs: Layered Application Guidelines
The 5-layer architecture
My application has about 50 entities that are displayed in grid format in the UI. All 50 entities have CRUD operations. Most of the operations have the standard flow
ie. for get, read entities from repository, convert to DTO and return a list of DTO's.
for create/update/delete - get DTO's - convert to entities, use repository to create/update/delete on DB, return updated DTOs
Mind you that for SOME entities, there are also some entity specific operations that have to be done.
Currently, we have a get/create/update/delete method for all our entities like
getProducts
createProducts
updateProducts
getCustomers
createCustomers
updateCustomers
in each of these methods, we use the Product/Customer repository to perform the CRUD operation AFTER conversion from entity -> dto and vice versa.
I feel there is a lot of code repetition and there must be a way by which we can remove so many of these methods.
Can i use some pattern (COMMAND PATTERN) to get away with code repetition?
Have a look at the Spring Data JPA or here project. It does away with boilerplate code for DAO.
I believe it basically uses AOP to interpret calls like
findByNameandpassword (String name,String passwd)
to do a query based upon the parameters passed in selecting the fields in the method name (only an interface).
Being a spring project it has very minimal requirements for spring libraries.
Basically, you have 2 ways to do this.
First way: Code generation
Write a class that can generate the code given a database schema.
Note that this you will create basic classes for each entity.
If you have custom code (code specific to certain entities) you can put that in subclasses so that it doesn't get overwritten when you regenerate the basic classes.
Object instatiation should be via Factory methods so that the correct subclass is used.
Make sure you add comments in the generated code that clearly states that the code is generated automatically (so that people don't start editing them directly).
Second way: Reflection
This solution, while being more elegant, is also more complex.
Instead of generating one basic class for each entity you have one basic class that can handle any entity. The class would be using reflection to access the DTO:s.
If you have custom code (code specific to certain entities) you can put that in other classes. These other classes would be injected into the generic class.
Using reflection would require a strict naming policy on your DTO:s.
Conclusion
I have been in a project using the first method in a migration project to generate DTO classes for the service interface between the new application server (running java) and the fat clients and it worked quite well. We had more than 100 generated DTO classes. I am aware that what you are attempting is slighty different. Editing database records is a generic problem (all projects need it) but there aren't (m)any frameworks for it.
I have been thinking about creating a generic tool or framework for it but I have never gotten around to it.
What is the accepted practice to use multiple database 'models' in a Spring / Hibernate combo ?
Would appreciate some help on an issue that has me scratching my head, as I am no expert in Spring/Hibernate !
We are developing a web project that up until now has been built to the specification of its first customer. All the database tables are mapped to POJOs and we use Hibernate Annotations. Very simply, the project is a CRUD application that allows end users to update database information via a front end.
We now need to support a new customer, but this customer has a slightly different specification; we will have changes to a number of tables' columns and datatypes.
We don't want to combine into one table, as this bloats up the database with lots of NULL columns (there will be 10+ unique columns per customer in some table).
The front end we can handle easily enough, as we just convert to and from JSON and the front end has been implemented per-customer from the ground up. But the backend is a bit more complicated.
We have tried a prototype where we override two tables at runtime; we converted two corresponding model classes to interfaces and implemented a concrete class per customer, loaded via the Spring configuration, e.g for a "products" table, we tried:
package com.mycompany.generic.model;
public interface Product
and then
package com.mycompany.customera.model;
#Table(name="products")
public class CustomerAProduct implements Properties {
String colour;
int weight;
}
or
package com.mycompany.customerb.model;
#Table(name="products")
public class CustomerBProduct implements Properties {
String colour;
int volume;
Double price;
}
..where Spring loads, as a runtime option, com.mycompany.customera or customerb depending on configuration, along with any customer-specific validations/service classes to act on the new POJO's. You see that the underlying columns can be different.
However, I am hesitate to pitch into implementing this, because..
Almost every model class will need converting and implementing per-customer, not just the ones that are different. This is because we have many joins (OneToMany etc) within the model classes, Hibernate does not let you join to an interface (eg HHH-4338)
some sort of util/factory is required to generate new instances of classes, as where we used to do new Properties we do not know whether to use new CustomerAProperties() or new CustomerBProperties() (for the same reason, we cannot use TargetEntity to solve the above problem, because this requires a .class file which cannot be set in the code)
These seem pretty major downsides so I am trying to research a better way to do it. We can build per-customer, via Maven, but then I am not sure how to implement this in a way that isn't going to break Eclipse while we develop locally..
Or, is there some other method that I am not aware of ?
thanks in advance for any suggestions or pointers on what to research etc.
Or, is there some other method that I am not aware of ?
Any reason you cannot switch from annotation based mapping to xml mapping?
Each customer gets a set of XML mapping files. Now you only need to subclass when the model truly differs between customers.
I've been using JPA on a small application I've been working on. I now have a need to create a data structure that basically extends or encapsulates a graph data structure object. The graph will need to be persisted to the database.
For persistable objects I write myself, it is very easy to extend them and have the extending classes also persist easily. However, I now find myself wanting to use a library of graph related objects (Nodes, edges, simple graphs, directed graphs, etc) in the JGrahpT library. However, the base classes are not defined as persistable JPA objects, so I'm not sure how to get those classes to save into the database.
I have a couple ideas and I'd like some feedback.
Option 1)
Use the decorator design pattern as I go along to add persistence to an extended version of the base class.
Challenges:
-- How do I persist the private fields of a class that are needed for it to be in the correct state? Do I just extend the class add an ID field, and mark it as persistable? How will JPA get the necessary fields from the parent class? (Something like ruby's runtime class modification would be awesome here)
-- There is a class hierarchy (Abstract Graph, Directed Graph, Directed Weighted Graph, etc.). If I extend to get persistence, extending classes still won't have the common parent class. How do I resolve this? (Again, Something like ruby's runtime class modification would be awesome here)
Option 2) Copy paste the entire code base. Modify the source code of each file to make it JPA compatible.
-- obviously this is a lot of work
I'm sure there are other options.. What have you got for me SO???
Do the base classes follow the JavaBeans naming conventions? If so you should be able to map them using the XML syntax of JPA.
This is documented in Chapter 10 of the specification:
The XML descriptor is intended to
serve as both an alternative to and an
overriding mechanism for Java language
metadata annotations.
This XML file is usually called orm.xml. The schema is available online
Your options with JPA annotations seem pretty limited if you're working with a pre-existing library. One alternative would be to use something like Hibernate XML mapping files instead of JPA. You can declare your mappings outside of the classes themselves. Private fields aren't an issue, Hibernate will ignore access modifiers via reflection. However, even this may end up being more trouble than its worth depending on the internal logic of the code (Hibernate's use of special collections and proxies for instance, will get you in hot water if the classes directly access some of their properties instead of using getter methods internally).
On the other hand, I don't see why you'd consider option 2 'a lot of work'. Creating a ORM mapping isn't really a no brainer task no matter how you go about it, and personally I'd consider option 2 probably the least effort approach. You'd probably want to maintain it as a patch file so you could keep up with updates to the library, rather than just forking.
Edit: This is not a conflict on the theoretical level but a conflict on an implementation level.
Another Edit:
The problem is not having domain models as data-only/DTOs versus richer, more complex object map where Order has OrderItems and some calculateTotal logic. The specific problem is when, for example, that Order needs to grab the latest wholesale prices of the OrderItem from some web service in China (for example). So you have some Spring Service running that allows calls to this PriceQuery service in China. Order has calculateTotal which iterates over every OrderItem, gets the latest price, and adds it to the total.
So how would you ensure that every Order has a reference to this PriceQuery service? How would you restore it upon de-serializations, loading from DBs, and fresh instantiations? This is my exact question.
The easy way would be to pass a reference to the calculateTotal method, but what if your Object uses this service internally throughout its lifetime? What if it's used in 10 methods? It gets messy to pass references around every time.
Another way would be to move calculateTotal out of the Order and into the OrderService, but that breaks OO design and we move towards the old "Transaction Script" way of things.
Original post:
Short version:
Rich domain objects require references to many components, but these objects get persisted or serialized, so any references they hold to outside components (Spring beans in this case: services, repositories, anything) are transient and get wiped out. They need to be re-injected when the object is de-serialized or loaded from the DB, but this is extremely ugly and I can't see an elegant way to do it.
Longer version:
For a while now I've practiced loose coupling and DI with the help of Spring. It's helped me a lot in keeping things manageable and testable. A while ago, however, I read Domain-Driven Design and some Martin Fowler. As a result, I've been trying to convert my domain models from simple DTOs (usually simple representations of a table row, just data no logic) into a more rich domain model.
As my domain grows and takes on new responsibilities, my domain objects are starting to require some of the beans (services, repositories, components) that I have in my Spring context. This has quickly become a nightmare and one of the most difficult parts of converting to a rich domain design.
Basically there are points where I am manually injecting a reference to the application context into my domain:
when object is loaded from Repository or other responsible Entity since the component references are transient and obviously don't get persisted
when object is created from Factory since a newly created object lacks the component references
when object is de-serialized in a Quartz job or some other place since the transient component references get wiped
First, it's ugly because I'm passing the object an application context reference and expecting it to pull out by name references to the components it needs. This isn't injection, it's direct pulling.
Second, it's ugly code because in all of those mentioned places I need logic for injecting an appContext
Third, it's error prone because I have to remember to inject in all those places for all those objects, which is harder than it sounds.
There has got to be a better way and I'm hoping you can shed some light on it.
I would venture to say that there are many shades of gray between having an "anemic domain model" and cramming all of your services into your domain objects. And quite often, at least in business domains and in my experience, an object might actually be nothing more than just the data; for example, whenever the operations that can be performed on that particular object depend on multitude of other objects and some localized context, say an address for example.
In my review of the domain-driven literature on the net, I have found a lot of vague ideas and writings, but I was not unable to find a proper, non-trivial example of where the boundaries between methods and operations should lie, and, what's more, how to implement that with current technology stack. So for the purpose of this answer, I will make up a small example to illustrate my points:
Consider the age-old example of Orders and OrderItems. An "anemic" domain model would look something like:
class Order {
Long orderId;
Date orderDate;
Long receivedById; // user which received the order
}
class OrderItem {
Long orderId; // order to which this item belongs
Long productId; // product id
BigDecimal amount;
BigDecimal price;
}
In my opinion, the point of the domain-driven design is to use classes to better model the relationships between entities. So, an non-anemic model would look something like:
class Order {
Long orderId;
Date orderDate;
User receivedBy;
Set<OrderItem> items;
}
class OrderItem {
Order order;
Product product;
BigDecimal amount;
BigDecimal price;
}
Supposedly, you would be using an ORM solution to do the mapping here. In this model, you would be able to write a method such as Order.calculateTotal(), that would sum up all the amount*price for each order item.
So, the model would be rich, in a sense that operations that make sense from a business perspective, like calculateTotal, would be placed in an Order domain object. But, at least in my view, domain-driven design does not mean that the Order should know about your persistence services. That should be done in a separate and independent layer. Persistence operations are not part of the business domain, they are the part of the implementation.
And even in this simple example, there are many pitfalls to consider. Should the entire Product be loaded with each OrderItem? If there is a huge number of order items, and you need a summary report for a huge number of orders, would you be using Java, loading objects in memory and invoking calculateTotal() on each order? Or is an SQL query a much better solution, from every aspect. That is why a decent ORM solution like Hibernate, offers mechanisms for solving precisely these kind of practical problems: lazy-loading with proxies for the former and HQL for the latter. What good would be a theoretically sound model be, if report generation takes ages?
Of course, the entire issue is quite complex, much more that I'm able to write or consider in one sitting. And I'm not speaking from a position of authority, but simple, everyday practice in deploying business apps. Hopefully, you'll get something out of this answer. Feel free to provide some additional details and examples of what you're dealing with...
Edit: Regarding the PriceQuery service, and the example of sending an email after the total has been calculated, I would make a distinction between:
the fact that an email should be sent after price calculation
what part of an order should be sent? (this could also include, say, email templates)
the actual method of sending an email
Furthermore, one has to wonder, is sending of an email an inherent ability of an Order, or yet another thing that can be done with it, like persisting it, serialization to different formats (XML, CSV, Excel) etc.
What I would do, and what I consider a good OOP approach is the following. Define an interface encapsulating operations of preparing and sending an email:
interface EmailSender {
public void setSubject(String subject);
public void addRecipient(String address, RecipientType type);
public void setMessageBody(String body);
public void send();
}
Now, inside Order class, define an operation by which an order "knows" how to send itself as an email, using an email sender:
class Order {
...
public void sendTotalEmail(EmailSender sender) {
sender.setSubject("Order " + this.orderId);
sender.addRecipient(receivedBy.getEmailAddress(), RecipientType.TO);
sender.addRecipient(receivedBy.getSupervisor().getEmailAddress(), RecipientType.BCC);
sender.setMessageBody("Order total is: " + calculateTotal());
sender.send();
}
Finally, you should have a facade towards your application operations, a point where the actual response to user action happens. In my opinion, this is where you should obtain (by Spring DI) the actual implementations of services. This can, for example, be the Spring MVC Controller class:
public class OrderEmailController extends BaseFormController {
// injected by Spring
private OrderManager orderManager; // persistence
private EmailSender emailSender; // actual sending of email
public ModelAndView processFormSubmission(HttpServletRequest request,
HttpServletResponse response, ...) {
String id = request.getParameter("id");
Order order = orderManager.getOrder(id);
order.sendTotalEmail(emailSender);
return new ModelAndView(...);
}
Here's what you get with this approach:
domain objects don't contain services, they use them
domain objects are decoupled from actual service implementation (e.g. SMTP, sending in separate thread etc.), by the nature of the interface mechanism
services interfaces are generic, reusable, but don't know about any actual domain objects. For example, if order gets an extra field, you need change only the Order class.
you can mock services easily, and test domain objects easily
you can test actual services implementations easily
I don't know if this is by standards of certain gurus, but it a down-to-earth approach that works reasonably well in practice.
Regardinig
What if your Order needs to send out
an e-mail every time the total is
calculated?
I would employ events.
If it has some meaning for you when an order computes its total, let it raise an event as eventDispatcher.raiseEvent(new ComputedTotalEvent(this)).
Then you listen for this type of events, and callback your order as said before to let it format an email template, and you send it.
Your domain objects remains lean, with no knowledge about this your requirement.
In short, split your problem into 2 requirements:
- I want to know when an order computes its total;
- I want to send an email when an order has a (new and different) total;
I've found the answer, at least for those using Spring:
6.8.1. Using AspectJ to dependency inject domain objects with Spring
The simplest approach that I can think is to add some logic into your data access layer that will inject a domain object with its dependencies before returning it to a higher layer (usually called the service layer). You could annotate each class's properties to indicate what needs to get wired up. If you're not on Java 5+, you could implement an interface for each component that needs to be injected, or even declare this all in XML and feed that data to the context that will do the wiring. If you wanted to get fancy, you could pull this out into an aspect and apply it globally across your data access layer so all methods that pull out domain objects will wire up them up just after they are returned.
Perhaps what you want is a kind on reference object, that would serialize as a global reference (an URI for instance) and that would be able to resurrect as a proxy when de-serialized elsewhere.
The Identity Map pattern may help with your scenario. Check the article Patterns In Practice written by Jeremy Miller where he discuss about this pattern.