Call service from Repository in spring boot - spring

Am new to Spring boot, i have seen example where we create repository to perform various operarion with the given Object. here is the sample one
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
so from the rest client if i send People jason
http://localhost:8080/people{ .... }
it inserts to the Database, internally it calls save method.
Here after calling from the REST client , i want to do some validation or business login and then insert to the database, how can i do it? It means i want to call a service method to do all the business logic and then insert so how can i call service method from repository class?

This repository is an interface and will allow you to perform various operations (here operations means DB related operations) involving Person objects. It gets these operations by extending the PagingAndSortingRepositry interface defined in Spring Data Commons.
At runtime, Spring Data REST will create an implementation of this interface automatically. Then it will use the #RepositoryRestResource annotation to direct Spring MVC to create RESTful endpoints at /people.
I don't think your requirements can be fulfilled with having the "#RepositoryRestResource" on the repository. You may want to create a proper sprint-boot application with the api, service and repo layer to perform the tasks you want to perform.

Related

Transaction - Springboot(JHipster) - RestService: how to

I have a microservice created with JHipster(SpringBoot+JPA) exposing a rest api.
During a save operation over an Entity I need to manage the transaction because I must execute another update over the DB (using other Entities).
How can I do this?
Using the tradictional approach (JDBC) I got the connection and create a transaction over it, make all the queries and finally close the transaction(commit/rollback).
With JPA I have an Entity, but I find no way to specify to begin/end(manage) the transaction programmatically.
You have many alternatives, here are few ones:
define a service (a class annotated with #Service) and annotate with #Transactional the public method that implements your logic
manage transaction manually through the EntityManager injected into your service class constructor
create a custom Repository
Check the Spring docs

Adding new DB support in spring data

Currently spring data has multiple db support (mysql, cassandra, mongo.. very big list), however i want to add my custom repository from the scratch like adding custom db support in spring data. I don't want to extend any existing repositories, instead I want to create a parallel repository strutcutre for my custom datasource. Looking at current implementation it looks like tedious task. It would be a great if someone could help me with minimal requirement to do this.
You could create a repository annotated bean where you would inject EntityManager or the proper bean that is acting like that, depending on database type that you are using.
#Repository
public class MyCustomRepositoryImpl implements MyCustomRepository {
#Autowired
private EntityManager entityManager;
//the methods that you are going to create.
}
For more details see:
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
Chapter: 1.3 Custom implementations for Spring Data repositories

Protect data for spring-data-rest

I am using Spring Data Rest to expose JPA repositories to our React front-end application.
And I also use Spring Security and JWT to protect REST APIs.
For examples, we have Entity and Repository as below:
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
....
}
public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {
}
Spring Data Rest will expose CustomerRepository to REST endpoint /api/customers
So our React application can call REST endpoints to get data. It works well.
However, someone with valid JWT token can use tools like Postman to fetch all customers data from the servers. Of course, we don't want this happen.
My questions:
How can we prevent such abnormal usage?
What's the best practice to use Spring Data Rest?
Your application exposes a REST API by using Spring Data REST. One of your entities is a Customer entity which is exposed through the CustomerRepository. On querying the list of all entities by calling /api/customers you only want those Customer entities to be listed that the querying principal has permission to see.
This can be done by annotating the method in question with #PreFilter or #PostFilter as explained in the Spring Security reference documentation. You need to specify some sort of condition.
An example:
#PostFilter(hasPermission(filterObject, 'read'))
public List<Customer> findAll();
Mind that #PostFilter iterates through the returned value, which can take some time, depending on the size of the returned list.

Multiple datasources in Spring Boot Repository Annotated Interface

My application is based on Spring Boot, Hibernate, MySQL using Spring Data JPA to stitch them.
Use case is to use slave db node for doing heavy read operations so as to avoid all traffic being served from master mysql node. One way of achieving this is to have multiple Entity Managers pointing to separate data sources(one to master and other to slave node). This way has been explained quite well in below SO questions and blogs.
Spring Boot, Spring Data JPA with multiple DataSources
https://scattercode.co.uk/2016/01/05/multiple-databases-with-spring-boot-and-spring-data-jpa/
Where I am stuck is to understand if there is a way I can inject different entity managers for different use cases in my Repository Annotated Interface.
The only way I see it can be done is extending repository with a custom implementation which gives uses custom entity manager annotated with relevant persistenceContext like below.
public interface CustomerRepository extends JpaRepository<Customer, Integer>, MyCustomCustomerRepository{
}
public class MyCustomCustomerRepositoryImpl implements MyCustomCustomerRepository {
#PersistenceContext(unitName = "entityManagerFactoryTwo")
EntityManager entityManager;
}
I would like to avoid doing this custom implementation. Any help around solving this use case(which I feel should be very common) would be appreciated.
NOTE: Entities are same in both databases so giving separate packages for entity scanning and similar solutions might not work.
Here is a nice sample you can use:
dynamic-datasource-routing-with-spring.
Inside you can find an AbstractRoutingDatasource + an interceptor for a custom annotation that wires the service method to a required database.
However you can just use datasource switch explicitly.
Below is the pull request that shows the diff and how I made it work with most configurations annotation driven instead of xml. It is based on cra6's answer above. i.e. using spring's RoutingDataSource capability.
https://github.com/himanshuvirmani/rest-webservice-sample/pull/1/files

How to hide spring data repository functions in service class?

I am using spring data JPA repository, my requirement is when i call repository class methods in service class it should show only custom methods like addUser(X,Y) instead of save().
Few things i understand, implementation of spring repository is provided by spring framework at runtime, So we cannot provide out own implementation. (This will overhead).
All methods in JPARepository is public only, so its obivious when we implement this interface all methods will be visible through out.
I am thinking of using DAO and Repository both at same time. DAO will provide custom function signature and repository will implement DAO interface.
Any Hack ?
If you don't want the methods from JpaRepository or CrudRepository, don't extend those but just Repository instead. It is perfectly fine to have a repository interface like
MyVeryLimitedRepository extends Repository<User, Long> {
User findByName(String name);
}
Of course methods like addUser(X,Y) will need a custom implementation.
You can very well use DAO pattern in this case .
By implementing DAO Pattern in Service Class
You create a wrapper between Service and Repository.
You can custom code your DAO layer to only expose custom methods to service layer

Resources