I don't know so much about DDD repository pattern but the implementation in Spring is confusion me.
public interface PersonRepository extends JpaRepository<Person, Long> { … }
As the interface extends JpaRepository (or MongoDBRepository...), if you change from one db to another, you have to change the interface as well.
For me an interface is there to provide some abstraction, but here it's not so much abstract...
Do you know why Spring-Data works like that?
You are right, an Interface is an abstraction about something that works equals for all implementing classes, from an outside point of view.
And that is exactly what happens here:
JpaRepository is a common view of all your JPA Repositories (for all the different Entities), while MongoDBRepository is the same for all MongoDB Entities.
But JpaRepository and MongoDBRepository have nothing in common, except the stuff that is defined in there common super Interfaces:
org.springframework.data.repository.PagingAndSortingRepository
org.springframework.data.repository.Repository
So for me it looks normal.
If you use the classes that implement your Repository then use PagingAndSortingRepository or Repository if you want to be able to switch from an JPA implementation to an Document based implementation (sorry but I can not imagine such a use case - anyway). And of course your Repository implementation should implement the correct interface (JpaRepository, MongoDBRepository) depending on what it is.
The reasoning behind this is pretty clearly stated in this blog post http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/.
Defining this interface serves two purposes: First, by extending JpaRepository we get a bunch of generic CRUD methods into our type that allows saving Accounts, deleting them and so on. Second, this will allow the Spring Data JPA repository infrastructure to scan the classpath for this interface and create a Spring bean for it.
If you do not trust sources so close to the source (pun intended) it might be a good idea to read this post as well http://www.brucephillips.name/blog/index.cfm/2011/3/25/Using-Spring-Data-JPA-To-Reduced-Data-Access-Coding.
What I did not need to code is an implementation of the PersonRepository interface. Spring will create an implementation of this interface and make a PersonRepository bean available to be autowired into my Service class. The PersonRepository bean will have all the standard CRUD methods (which will be transactional) and return Person objects or collection of Person objects. So by using Spring Data JPA, I've saved writing my own implementation class.
Until M2 of Spring Data we required users to extend JpaRepository due to the following reasons:
The classpath scanning infrastructure only picked up interfaces extending that interface as one might use Spring Data JPA and Spring Data Mongo in parallel and have both of them pointed to the very same package it would not be clear which store to create the proxy for. However since RC1 we simply leave that burden to the developer as we think it's a rather exotic case and the benefit of just using Repository, CrudRepository or the like outweights the effort you have to take in the just described corner case. You can use exclude and include elements in the namespace to gain finer-grained control over this.
Until M2 we had transactionality applied to the CRUD methods by redeclaring the CRUD methods and annotating them with #Transactional. This decision in turn was driven by the algorithm AnnotationTransactionAttributeSource uses to find transaction configuration. As we wanted to provide the user with the possibility to reconfigure transactions by just redeclaring a CRUD method in the concrete repository interface and applying #Transactional on it. For RC1 we decided to implement a custom TransactionAttributeSource to be able to move the annotations back to the repository CRUD implementation.
Long story short, here's what it boils down to:
As of RC1 there's no need to extend the store specific repository interface anymore, except you want to…
Use List-based access to findAll(…) instead of the Iterable-based one in the more core repository interfaces (allthough you could simply redeclare the relevant methods in a common base interface to return Lists as well)
You want to make use of the JPA-specific methods like saveAndFlush(…) and so on.
Generally you are much more flexible regarding the exposure of CRUD methods since RC1 as you can even only extend the Repository marker interface and selectively add the CRUD methods you want to expose. As the backing implementation will still implement all of the methods of PagingAndSortingRepository we can still route the calls to the instance:
public interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
List<T> findAll();
T findOne(ID id);
}
public interface UserRepository extends MyBaseRepository<User, Long> {
List<T> findByUsername(String username);
}
In that example we define MyBaseRepository to only expose findAll() and findOne(…) (which will be routed into the instance implementing the CRUD methods) and the concrete repository adding a finder method to the two CRUD ones.
For more details on that topic please consult the reference documentation.
Related
I'm working through a spring mvc video series and loving it!
https://www.youtube.com/channel/UCcawgWKCyddtpu9PP_Fz-tA/videos
I'd like to learn more about the specifics of the exact architecture being used and am having trouble identifying the proper name - so that I can read further.
For example, I understand that the presentation layer is MVC, but not really sure how you would more specifically describe the pattern to account for the use of service and resource objects - as opposed to choosing to use service, DAO and Domain objects.
Any clues to help me better focus my search on understanding the layout below?
application
core
models/entities
services
rest
controllers
resources
resource_assemblers
Edit:
Nathan Hughes comment clarified my confusion with the nomenclature and SirKometa connected the architectural dots that I was not grasping. Thanks guys.
As far as I can tell the layout you have mentioned represents the application which communicates with the world through REST services.
core package represents all the classes (domain, services, repositories) which are not related to view.
model package - Assuming you are aiming for the typical application you do have a model/domain/entity package which represents your data For example: https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/models/entities/Account.java.
repository package - Since you are using Spring you will most likely use also since spring-data or even spring-data-jpa with Hibernate as your ORM Library. It will most likely lead you to use Repository interfaces (author of videos you watch for some reason decided not to use it though). Anyway it will be your layer to access database, for example: https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/repositories/jpa/JpaAccountRepo.java
service package will be your package to manipulate data. It's not the best example but this layer doesn't access your database directly, it will use Repositories to do it, but it might also do other things - it will be your API to manipulate data in you application. Let's say you want to have a fancy calculation on your wallet before you save it to DB, or like here https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/services/impl/AccountServiceImpl.java you want to make sure that the Blog you try to create doesn't exist yet.
controllers package contain all classes which will be used by DispacherServlet to take care of the requests. You will read "input" from the request, process it (use your Services here) and send your responses.
resource_assemblers package in this case is framework specific (Hateoas). As far as I can tell it's just a DTO for your json responses (for example you might want to store password in your Account but exposing it through json won't be a good idea, and it would happen if you didn't use DTO).
Please let me know if that is the answer you were looking for.
This question may be of interest to you as well as this explanation.
You are mostly talking about the same things in each case, Spring just uses annotations so that when it scans them it knows what type of object you are creating or instantiating.
Basically everything request flows through the controller annotated with #Controller. Each method process the request and (if needed) calls a specific service class to process the business logic. These classes are annotated with #Service. The controller can instantiate these classes by autowiring them in #Autowire or resourcing them #Resource.
#Controller
#RequestMapping("/")
public class MyController {
#Resource private MyServiceLayer myServiceLayer;
#RequestMapping("/retrieveMain")
public String retrieveMain() {
String listOfSomething = myServiceLayer.getListOfSomethings();
return listOfSomething;
}
}
The service classes then perform their business logic and if needed, retrieve data from a repository class annotated with #Repository. The service layer instantiate these classes the same way, either by autowiring them in #Autowire or resourcing them #Resource.
#Service
public class MyServiceLayer implements MyServiceLayerService {
#Resource private MyDaoLayer myDaoLayer;
public String getListOfSomethings() {
List<String> listOfSomething = myDaoLayer.getListOfSomethings();
// Business Logic
return listOfSomething;
}
}
The repository classes make up the DAO, Spring uses the #Repository annotation on them. The entities are the individual class objects that are received by the #Repository layer.
#Repository
public class MyDaoLayer implements MyDaoLayerInterface {
#Resource private JdbcTemplate jdbcTemplate;
public List<String> getListOfSomethings() {
// retrieve list from database, process with row mapper, object mapper, etc.
return listOfSomething;
}
}
#Repository, #Service, and #Controller are specific instances of #Component. All of these layers could be annotated with #Component, it's just better to call it what it actually is.
So to answer your question, they mean the same thing, they are just annotated to let Spring know what type of object it is instantiating and/or how to include another class.
I guess the architectural pattern you are looking for is Representational State Transfer (REST). You can read up on it here:
http://en.wikipedia.org/wiki/Representational_state_transfer
Within REST the data passed around is referred to as resources:
Identification of resources:
Individual resources are identified in requests, for example using URIs in web-based REST systems. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server may send data from its database as HTML, XML or JSON, none of which are the server's internal representation, and it is the same one resource regardless.
I'm new to using Spring with Neo4j and I have a question about #Autowire for a GraphRepository.
Most examples I've seen use one #Autowire per Controller, but I have two Nodes I need to modify at the same time when a particular method is called in the controller. Should I simply #Autowire the repositories for both nodes (eg per the code below)? Is there any impact if I do this in a second controller with the same repositories as well (so if I had a ChatSessionController which also #Autowired ChatMessageService and ChatSessionService)?
ChatMessageController.java
#Controller
public class ChatMessageController {
#Autowired
private ChatMessageService chatMessageService;
#Autowired
private ChatSessionService chatSessionService;
#RequestMapping(value = "/message/add/{chatSessionId}", method = RequestMethod.POST)
#ResponseBody
#Transactional
public void addMessage(#RequestBody ChatMessagePack chatMessagePack,
#PathVariable("chatSessionId") Long chatSessionId) {
ChatMessage chatMessage = new ChatMessage(chatMessagePack);
chatMessageService.save(chatMessage);
// TODO: Make some modifications to the ChatSession as well
}
}
Any help would be much appreciated! I've been googling and looking through Stackoverflow to understand this better but I haven't found anything yet. Any pointers in the right directions would be great.
Another underlying question is, should I be (and can I?) modifying other Nodes in a GraphRepository that handles a particular node? Eg Should my GraphRepository be able to modify my GraphRespository?
Thanks!
I'm not convinced that this is a SO question, it's not really a Neo4J or Spring question either, it is more about the architecture of your application. However assuming that you understand the negatives of class fan out, and how to use the #Transactional annotation to achieve what you want then the answer to your question is that it is just fine to have many Repositories (Neo4J or otherwise, autowired or otherwise) in your class and in as many classes as you want.
Neo4J transactions default to Isolation level READ_COMMITTED and if you need anything else, you need to add the guards/locks yourself. Nested transactions are consideredd tobe the same transaction. The Spring #Transactional annotation relies on proxies that you should be aware of as they have implications when calling methods from within the same class.
I would go through this tuotorial over at Spring Data and get your head around how real world vs domain vs node models differ, there will be cases where one repository impacts another node type but I would think it is often transparent to you (i.e adding relationships). You can do what you like in each repository (the generic nature of them is largely confined to all of the built in CRUD and queries derived from finder-method names (see documentation ) using the #Query annotation, and some queries have side effects, but largely you should avoid it.
As you start adding multiple repositories to multiple controllers I think that your code will begin to smell bad and that you should consider encapsulating this business logic off on its own somewhere, neatly unit tested. I also wouldn't tie myself to one controller per data object, it would be fine to have a single ChatController with a POST/chat/ to create a new session and POST /chat/{sessionId} to add a message. Intersting questions on Programmers:
How accurate is "Business logic should be in a service, not in a model?"
Best Practices for MVC Architecture
MVC Architecture — How many Controllers do I need?
I found out that there is an interface called GraphRepository. I have a repository for users implementing a homemade interface that does its job, but I was wondering, shouldn't I implement GraphRepository instead ? Even if it will be quite long to implement and some methods will be useless, I think it is a standard and I already re-coded a lot of methods that are defined in this interface.
So should I write "YAGNI" code or not respect the standard ?
What is your advice ?
you don't need to actually implement GraphRepository but extend it. the principals of Spring-Data is that all the boiler-plate CRUD code is taken care of (by proxying at startup time) so all you have to do is create an interface for your specific entity extending GraphRepository and then add only specific methods that you require.
for example; if i have an entity CustomerNode, to create standard CRUD methods, i can create a new interface CustomerNodeRepository extends GraphRepository<CustomerNode,Long>. all the methods from GraphRepository (e.g. save, findAll, findOne, delete, deleteAll, etc.) are now accessible from CustomerNodeRepository and implemented by Spring-Data-Neo4J without having to write a single line of implementation code.
the pattern now allows you to work on your specific repository code (e.g. findByNameAndDateOfBirth) rather than the simple CRUD stuff.
Spring-Data package is very useful for repository interaction. it can reduce huge amounts of code (have seen 80%+ reduction in code lines) and would highly recommend using it
edit: implementing custom execution
if you want to add your own custom behavior to a Repository method, you create the concept of merging interfaces and custom implementation. for example, lets say i want to create a method called findCustomerNodeBySomeStrangeCriteria and to do this, i actually want to link off to a relational database to perform the function.
first we define a separate, standalone interface that only includes our 'extra' method.
public interface CustomCustomerNodeRepository {
List<CustomerNode> findCustomerNodeBySomeStrangeCriteria(Object strangeCriteria);
}
next we update our normal interface to extend not only GraphRepository, but our new custom one too
public interface CustomerNodeRepository extends GraphRepository<CustomerNode,Long>, CustomCustomerNodeRepository {
}
the last piece, is to actually implement our findCustomerNodeBySomeStrangeCriteria method
public class CustomerNodeRepositoryImpl implements CustomCustomerNodeRepository {
public List<CustomerNode> findCustomerNodeBySomeStrangeCriteria(Object criteria) {
//implementation code
}
}
so, there's a couple of points to note;
we create a separate interface to define any custom methods that have custom implementations (as distinct from Spring-Data compatible "findBy..." methods)
our CustomerNodeRepository interface (our 'main' interface) extends both the GraphRepository and our 'custom' one
we implement only the 'custom' method in a class that implements only the custom interface
the 'custom' implementation class must (by default) be called our 'main' interface Impl to be picked up by Spring Data (so in this case CustomNodeRepositoryImpl)
under the covers, Spring Data delivers a proxy implementation of CustomerNodeRepository as a merge of the auto-built GraphRepository and our class implementing CustomCustomerNodeRepository. the reason for the name of the class is to allow Spring Data to pick it up easily/successfully (this can be overwritten so it doesn't look for *Impl)
I have a lot of entities in application and I use JPA implementation for persisting them, therefore most of CRUD methods across DAOs are similar (see example class diagram below).
For this purpose there is interface DAOTemplate which contains methods available for all entities and is implemented by abstract class AbstractDAO.
Some entities require additional methods such as findByEmail for User entity. For that purpose there is DAO interface with such methods e.g. UserDAO.
Now I want to write integration tests for all methods (those in DAOTemplate and UserDAO). What is the best solution? Should I somehow (how?) test AbstractDAO and then only special methods in UserDAOTest or should I test all methods in UserDAOTest and also in other test cases for other entities? I'm trying to avoid the second solution because I don't like it.
Thanks for answers.
You should test all methods in UserDAOTest since calling them will have different results depending on what entity you are trying to persist. You won't only be testing your DAO code but also your entities, their annotations and their relationships.
But in following the DRY principle you should not re-implement the AbstractDAO methods in each test, but you can for instance create an AbstracDAOTest that all UserDAOTest inherits from. Having your tests match your code like that should look quite nice..
I had similar situation. If you have a lot of DAO it can be slow to test again same methods.
I created dummy entity and DAO implementation only for testing.
I'm using JAX-RS to provide an HTTP-based interface to manage a data model. The data model is stored in a database and interacted with via JPA.
This allows me to modify the interface to the data model to suit REST clients and mostly seems to work quite well. However, I'm not sure how to handle the scenario where a method provided by a JAX-RS resource requires a transaction, which affects the JPA get, update, commit-on-tx-end pattern, because there is only a transaction wrapping the get operation, so the update is never committed. I can see the same problem occurring if a single REST operation requires multiple JPA operations.
As I'm using Spring's transaction support, the obvious thing to do is to apply #Transactional to these methods in the JAX-RS resources. However, in order for this to work, Spring needs to manage the lifecycle of the JAX-RS resources, and the useage examples I'm aware of have resources being created via `new' when needed, which makes me a little nervous anyway.
I can think of the following solutions:
update my JPA methods to provide a transaction-managed version of everything I want to do from my REST interface atomically. Should work, keeps transactions out of the JAX-RS layer, but prevents the get, update, commit-on-tx-end pattern and means I need to create a very granular JPA interface.
Inject Resource objects; but they are typically stateful holding at least the ID of the object being interacted with
Ditch the hierarchy of resources and inject big, stateless super resources at the root that manage the entire hierarchy from that root; not cohesive, big services
Have a hierarchy of injected, stateless, transaction-supporting helper objects that 'shadow' the actual resources; the resources are instantiated and hold ths state but delegate method invocations to the helper objects
Anyone got any suggestions? It's quite possible I've missed some key point somewhere.
Update - to work around the lack of a transaction around the get, update, commit-on-tx-close flow, I can expose the EntityManager merge(object) method and call it manually. Not neat and doesn't solve the larger problem though.
Update 2 #skaffman
Code example:
In JPA service layer, injected, annotations work
public class MyEntityJPAService {
...
#Transactional(readOnly=true) // do in transaction
public MyEntity getMyEntity(final String id) {
return em.find(MyEntity.class, id);
}
In JAX-RS resource, created by new, no transactions
public class MyEntityResource {
...
private MyEntityJPAService jpa;
...
#Transactional // not injected so not effective
public void updateMyEntity(final String id, final MyEntityRepresentation rep) {
MyEntity entity = jpa.getMyEntity(id);
MyEntity.setSomeField(rep.getSomeField());
// no transaction commit, change not saved...
}
I have a few suggestions
Introduce a layer between your JPA and JAX-RS layers. This layer would consist of Spring-managed #Transactional beans, and would compose the various business-level operations from their component JPA calls. This is somewhat similar to your (1), but keeps the JPA layer simple.
Replace JAX-RS with Spring-MVC, which provides the same (or similar) functionality, including #PathVariable, #ResponseBody, etc.
Programmatically wrap your JAX-RS objects in transactional proxies using TransactionProxyFactorybean. This would detct your #Transactional annotations and generate a proxy that honours them.
Use #Configurable and AspectJ LTW to allow Spring to honour #Transactional even if you create the object using `new. See 8.8.1 Using AspectJ to dependency inject domain objects with Spring