My Dao's are setup like:
UserDao
UserDaoImpl
My business layer are in service classes like:
UserService
UserServiceImpl
Now my Dao's have basic operations like get, update, save, etc.
I want to expose these methods in my service class without having to manually add these to each service interface.
How can I achieve this?
The point of having services is to aggregate DAO methods within a transaction, and to add business logic. If all your services are doing is wrapping individual DAO methods there is no point to having them. Using some framework like Grails (or Play, so you can still use Java if you want) data access methods are added to your domain objects dynamically, you can call them from the controller and have a lot less CRUD code to mess with (but still have services as an option in the event you need them later).
If the service is doing nothing else besides CRUD operations, and no other service has need for that DAO, I'd see no reason why you can't just put those operations in the service implementation and dispense with the DAO.
It's easy enough to just use the service as a pass-through:
public interface FooService {
Foo find(Long id); // Same as DAO signature
}
#Service
public class FooServiceImpl implements FooService {
#Resource(name = "fooRepository")
private FooRepository fooRepository;
public Foo find(Long id) { return this.fooRepository.find(id); }
}
It's possible to write a generic DAO:
public interface GenericRepository<V, K extends Serializable> {
V find(K key);
List<V> find();
K save(V value);
void update(V value);
void delete(V value);
}
Yes this is kind of variation of Adapter pattern
You can also extend the UserDaoImpl to UserServiceImpl for example
UserServiceImpl extend UserDaoImpl implements UserService{
// Rest of the Service implementation
}
Related
If I have a standard CrudRepository and a Controller like below, is this thread safe? I know that this class is treated as a singleton, but wasn't sure if Spring handles repositories in a special way that allows for no handling on my side.
#Controller
public class TestController {
#Autowired
private TestRepository testRepository;
#RequestMapping(path = "/test")
public void addTest() {
TestObj o = new TestObj();
testRepository.save(o);
}
}
public interface TestRepository extends CrudRepository<TestObj, Integer> {
}
The standard CrudRepository is not threadSafe.But i think that you ask about how the data concurrent access are handling?
first you should to know that there are several phenomes that may occur when using transaction simultaneously and can affect the integrity of data such as: lost update, dirty read, unrepeatable read, last commit wins and phantom read.
For managing these phenomes according to your requirement spring offer the possibility to specify the desired isolation level inside #Transactional annotation.
for more information :
https://www.baeldung.com/spring-transactional-propagation-isolation
https://docs.spring.io/spring-data/data-jpa/docs/current/reference/html/#jpa.bootstrap-mode
Just started learning how to use Spring! As a best practice if you are working on a spring method and you need to add/leverage a piece of functionality that you've already built out in another Spring Class which is accessible via the API, should you use the established API or call it directly?
Suppose you have a CustomerService component
#Service
public class CustomerService {
public Customer getCustomerById(CustomerId id) {
//your code here
}
}
Suppose now that you have an OrderService that needs to find the customer before placing an new order. You definitively would prefer to find the customer using your existing CustomerService API.
#Service
public class OrderService {
#Autowire private CustomerService customerService;
public void placeOrder(Order order, CustomerId custId) {
Customer customer = customerServive.getCustomerById(custId);
//your code here
}
}
That totally make sense.
Now suppose you have a controller to expose your CustomerService to your web clients.
#RestController
public CustomerController {
#Autowire private CustomerService customerService;
#GET("/customer/{custId}")
public Customer getCustomer(#Param CustomerId custId){
return customerService.getCustomerById(custId);
}
}
From you OrderServer you definitely don't need to/should not make an HTTP remote call to this HTTP service to get a customer. That would not make sense if they are both colocated in the JVM. It is a hell of a lot simpler and safer to just use your local service.
If however your CustomerService runs in a different process/JVM, one entirely different than the one it runs your OrderService than it would make sense to make a remote HTTP call to get your customer.
In a case like this, you probably would have a CustomerServiceGateway to make the remote call.
For example, in the orders api
interface CustomerService {
Order getCustomerById(CustomerId custId);
}
And then a gateway implementation:
#Service
public class CustomerServiceGateway implements CustomerService {
#Autowire private RestTemplate restTemplate;
Order getCustomerById(CustomerId custId) {
return restTemplate.getForObject("http://customer-api/customer/{custId}", custId);
}
}
This is an oversimplification, but even so you can see that is much harder to do and it only make sense if you try to invoke remote services.
I am attempting to get a reference to my repository interface (UserRepository) that extends CrudRepository within my custom implementation (UserRepositoryExtensionImpl) in order to gain access to all the methods provided by Spring JPA.
Crud Extension:
#Repository
public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser> {
...any custom spring JPA methods...
}
Extension Interface:
#Repository
public interface UserRepositoryExtension <T> {
public T put(T entity);
}
Custom Implementation:
public class UserRepositoryExtensionImpl implements UserRepositoryExtension<User> {
UserRepository userRepository;
#Autowired
public UserRepositoryExtensionImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public User put(User user) {
System.out.println(user + "was put");
// ...put logic here
return null;
}...
}
However, I am unable to inject UserRepository since a circular dependency exists (given that UserRepository extends the interface implemented by my UserRepositoryImpl). I am getting the following error:
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ' userRepositoryImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
A possible, but less than ideal solution would be to inject and EntityManager into UserRepositoryImp, but in that case, I do not have access to any of the Spring JPA methods provided by CrudRepository, or any additional methods that I might have created in UserRepository.
Any suggestions on how to get around this?
Any help would be greatly appreciated.
EDIT: As mentioned in #shelley's answer, I was able to solve this by making 3 changes:
Removing the #Repository from UserRepositoryExtensionImpl
Renaming UserRepositoryExtensionImpl to UserRepositoryImpl. Apparently this makes Spring aware of the implementation's existence. See Spring Doc
Removing my constructor and moving the #Autowired to the userRepository field
SUCCESS!
A couple small things need to be changed in order for this to work:
Remove the #Repository annotation from the custom repository interface (UserRepositoryExtension).
The custom repository implementation should actually be named "<StandardRepository>Impl" rather than "<CustomRepository>Impl". In your code example, this should be UserRepositoryImpl instead of UserRepositoryExtensionImpl.
As shelley pointed out, the naming is really important to make the autowire work. In the example below, I follow the right naming standard for my custom interface and its implementation. But my interface that extended the JpaRepository was named “ItemDao” instead of “ItemRepository”, this resulted in that spring ignored my custom implementation altogether...
OBS!!! Should be "ItemRepository"
#Repository
public interface ItemDao extends JpaRepository<Item, Long>, ItemRepositoryCustom {}
my interface
interface ItemRepositoryCustom {...}
my implementation class
class ItemRepositoryImpl implements ItemRepositoryCustom {...}
If anyone have similar problems, start by following the naming standard that is used in the spring documentation at the link below.
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
There is a well defined way to create custom repository implementations in Spring Data JPA which you should follow. Basically you need to extend CrudRepository so you don't have to inject an instance of it in your custom implementation.
I have solved problem by injecting ApplicationContext and getting bean in lazy way using applicationContext.getBean(UserRepository.class).
It works this way.
I found I way of how to do it without the need for #Autowire:
public interface UserRepository extends
UserRepositoryBasic,
UserRepositoryExtension
{
}
public interface UserRepositoryBasic extends
JpaRepository<User, String>
{
// standard Spring Data methods, like findByLogin
}
public interface UserRepositoryExtension
{
public void customMethod();
}
public class UserRepositoryExtensionImpl implements
UserRepositoryExtension
{
private final UserRepositoryBasic userRepositoryBasic;
// constructor-based injection
public UserRepositoryExtensionImpl(
UserRepositoryBasic userRepositoryBasic)
{
this.userRepositoryBasic = userRepositoryBasic;
}
public void customMethod()
{
// we can call all basic Spring Data methods using
// userRepositoryBasic
}
}
Well in this case I suggest to use the #Lazy annotation.
public class MyCustomRepositoryImpl implements MyCustomRepository {
#Lazy
#Autowired
private MyRepository myRepository;
#Override
public boolean customMethod() {
return myRepository.count() > 0;
}
}
With constructor parameter Spring tries to create the "basic" repository class which require you custom repository which requires you "basic" repository - the typical case with circular dependency.
Without #Lazy but with only the #Autowired it also won't work (there will be problem with factory bean for the basic repo).
I think in this case the #Lazy is the most elegant solution.
Can a service-layer object "service" a DAO-layer object? Or is does this violate the integrity of a properly layered architecture?
e.g.,
class MyService {
}
class MyDao {
private MyService myService;
}
I wouldn't do it. DAOs ought to deal with databases; services manage other services and DAOs to fulfill their use cases. It'd be better to have the service call the DAO and any other services that are required.
You risk a circular dependency with this arrangement.
The standard way of constructing services with DAO objects is to let the service encapsulate the DAO.
public class Service {
private DAO dao;
}
public class DAO {}
This is useful e.g., to let a service encapsulate multiple DAO objects, or to provide additional logic such as transaction demarcation in the service.
im programming a project and im trying to apply multitier architecture.
Right now ive got 2 EJB, business and persistence and a shared jar. Due a funcional requirment, persistence must be replaceable. I made an Interface called IPersistence.
Then I crated a remote session bean called "persistence" inside the persistence EJB and put the remote interface in the shared library. Now, i need to call an IPersitence using injection from the business. How can i do that? Maybe the whole idea is wrong. I need some advice.
Thanks!
Here is a simple example where you have a car repository/DAO that abstracts the persistence from the business logic by not exposing if it is stored in a database, file, XML etc. The business class then injects an instance to be able to - in this case - save to an database. However you could have made other classes that implemented the CarRepository and provide other means for saving data in your application without touching other parts of your code.
Persistence layer
Interface for the repository/DAO
#Local
public interface CarRepository {
List<Car> findAllCars();
// Many other methods
}
Repository (Domain driven design) or Data Access Object
#Stateless
public class CarSqlRepository implements CarRepository {
#PersistenceContext(unitName = "MyUnit")
private EntityManager entityManager;
public List<Car> findAllCars() {
}
// Many other methods
}
Service/business layer
#Stateless
public class CarService {
#Inject
private CarRepository carRepository;
public List<Car> findAllCars() {
return carRepository.findAllCars();
}
// Many other methods
}