Need a way to annotate service methods following repository pattern - java

I'm trying to refactor the existing code base of one of my project following Repository pattern, so that i can make the project more re-usable and testable.
I've written services, repositories, when I try to set Authentication, Authorization and Transactional annotation on service layer, I am facing issues.
These annotations works only on controller level, but not on service layer, so I want a way for annotate service methods.
Is it possible to do so?
It would be helpful, if someone points me samples using repository pattern on Play framework or better way to proceed further.

Authentication and authorization only make sense on a request, so sticking them on anything but a controller method is not going to work either way.
Transactional is just a helper annotation to wrap the entire request in a JPA transaction. It is usually advisable to do the wrapping yourself anyway, so you don't really need that. Example taken from the documentation:
#Inject
private JPAApi jpaApi;
public void updateSomething() {
// do something with the entity manager, per instance
// save, update or query model objects.
jpaApi.withTransaction(() -> {
EntityManager em = jpaApi.em();
Query query = em.createNativeQuery("update people set active = 1 where age > 18");
query.executeUpdate();
});
}

Related

How to force developers to write CustomAnnotation before each api Springboot

How can we force developer to write Developed Custom-annotation on rest api
Example :
We Developed annotation Called : ValidatePermission
what we need to do , displaying runtime error for developer that he missing annotation #ValidatePermission on API , when he tried to write new api
#ValidatePermission
#GetMapping("/details")
#PreAuthorize("hasAuthority('902')")
public ResponseEntity<CustDtlsInqDto> getCustomerDetails(#CurrentUser UserPrincipal currentUser,
#RequestParam(name = "poiNumber", required = false) String poiNumber,
#RequestParam(name = "cif", required = false) String cif) {
return ResponseEntity.ok(customerService.getCustomerDetailsByPoiOrCif(currentUser.getId(), poiNumber, cif));
}
Annotations usage cannot be forced in any way before or on compilation (at least I am not aware of any technique, feel free to correct me).
The only way to go is to perform a check-up during the unit testing phase. Simply write an unit test that scans through the REST API definition beans and its public methods (or annotated) to check up using teh Reflection API whether an annotation from a particular category (implementation details up to you) is present within the formal parameters of methods.
Gits Github: Find all annotated classes in a package using Spring
Baeldung: A Guide to the Reflections Library
Something looks to me weird in this approach.
So you say:
...displaying runtime error for developer that he missing annotation #ValidatePermission on API
Based on this phrase, let me suggest an alternative:
So the developer that runs the project locally (during the debugging session or maybe tests) should see an error if he/she didn't put the annotation on the methods of rest controller, right?
If so, Why don't you need the developers to put this annotation?
The main idea of my suggestion is: Why not letting spring to do it for you automatically?
You could implement some kind of aspect or if you don't want to use a spring aop and prefer 'raw plain spring', BeanPostProcessor, that would 'wrap' all the methods of class annotated with RestContoller (by creating a run-time proxy) and before running a controller method will executed the logic that was supposed to be supported by the annotation?
In the case of Web MVC, another approach is to implement an interceptor that will be invoked automatically by spring mvc engine and you'll be able to execute any custom logic you want there, you'll also be able to inject other beans (like auxiliary services) into the interceptor.
Read this article in case you're not familiar with these interceptors, you'll need preHandle methods as far as I understand.

How to structure controllers that communicate with databases

I'm pretty new to the concept of patterns. I am practising my dependency injection skills as well as using DAO principles. The code I have written works but I feel that it can be written in a more elegant fashion. I've tried restructuring it a pattern I saw but that complicated things so not sure if I implemented it correctly. As a general rule when a web application communicates with a database and throws out result, how should one structure their project?
I've heard of the MVC principle but that doesn't necessarily add database to the mix.
This is what I have so far:
A class containing a controller in a Controller package:
#RestController
public class ResponseController {
#Autowired
MongoBase dbConnection;
#RequestMapping(value = "/jsonresult", method = RequestMethod.GET)
#ResponseBody
public String jsonresult(#RequestParam(value = "id", required = true) String id){
return dbConnection.documentToJSON(id, Constants.database,Constants.collection);
}
#RequestMapping(value = "/alljsonresult", method = RequestMethod.GET)
#ResponseBody
public String alljsonresult(){
return dbConnection.allDocumentToJSON(Constants.database,Constants.collection);
}}
A class containing CRUD methods to the database in a Database package:
#Component
public class MongoBase {
#Autowired
MongoClient mongoClient;
public MongoBase() {
try {
mongoClient = new MongoClient("localhost", 27017);
} catch (Exception e) {
e.printStackTrace();
}
}
public void printAllCollection(String databaseName, String collectionName) {
...
}
So is there a better way/more efficient way of writing thi? Also I feel I haven't fully implemented DI in the Monogbase class since it contains the new keyword..
If you are using springboot, then you don't need this old style
also don't need to create mongoClient bean your self, spring boot help you in it
You just need to add following properties in application.properties file
#mongodb
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=app1
Also declares a spring-boot-starter-data-mongodb in your pom or gradle
it's a cool and super awesome dependency for accessing Data with MongoDB
you can read about it from here[https://spring.io/guides/gs/accessing-data-mongodb/]
suppose you have a domain
#Document(collection = "domain")
public class User {
#Id
private long id;
#Indexed(unique = true)
private String domain;
private boolean displayAds;
//getters and setters
}
Now if we need to perform curd operation on this domain, extends MongoRepository, you have CRUD function automatically. Spring data come with many magic findBy queries, review the official Spring data MongoDB – Query methods for detail.
public interface UserRepository extends MongoRepository<User, Long> {
Domain findFirstByDomain(String domain);
Domain findByDomainAndDisplayAds(String domain, boolean displayAds);
//Supports native JSON query string
#Query("{domain:'?0'}")
Domain findCustomByDomain(String domain);
#Query("{domain: { $regex: ?0 } })")
List<Domain> findCustomByRegExDomain(String domain);
}
UserRepository extends the MongoRepository interface and plugs in the type of values and id it works with: User and Long. Out-of-the-box, this interface comes with many operations, including standard CRUD operations (create-read-update-delete).
now you can easly use it in your controller
#RestController
public class ResponseController {
#Autowired
UserRepository userRepository;
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
User create(#RequestBody #Valid User user) {
return userRepository.create(user);
}
}
also you can do with it lot of things. you just need to go throw with it doc.
Also you you can use mongoTemplate for execute the query
#Autowired
MongoTemplate mongoTemplate;
When I build web applications I typically define the full chain as follows:
Client Side:
View - This is the V in MVC where you control visuals & user action derived workflow.
Controller - This is the C in MVC where workflow is managed. Most Client processing will go here and multiple Client calls can be made to get/send data or perform lookups.
Client - This is where you make a call to a REST web service and parse/deserialize the results/handle exceptions.
Server Side:
RestController (Sometimes Called Resource) - This is your REST API endpoint. Here you extract & validate a request.
Service - This is where most of your server logic will go. Sometimes you might have to make multiple data access calls or call other service functions.
DataAccessObject (Sometimes Called Provider) - This is your database interaction to pull data from your database into a model. CRUD operations (Create Read Update Delete)
Example Scenario:
Lets say we want to submit data & permissions for a given user
UserView.jsp - User types in user & permission data and hits submit.
UserController.java - validates User & permission data, does any necessary lookups, then calls UserClient.
UserClient.java - Builds the REST request and calls the /user/create REST endpoint.
UserRestController.java - Unpackages/Validates the request, then calls UserManagementService
UserManagementService.java - Server Logic happens here! Lets say I have two tables in my database. A User table and a Permissions table. I want to store the user information in the User table and the permission information in the permission table so I will call the UserDAO for the user data and the PermissionDAO for the permission data.
UserDAO & PermissionDAO - Saves The passed models to their respective tables.
Return to Service, Return to RestController, Return to Client (Parse Response), Return to Controller (Move the Workflow forward with a redirect or a success message).
Conclusion:
This may seem like a lot of in-between steps but this design provides a ton of flexibility, especially if your building large, complex web services. Each component has a specific purpose, follows an easy naming convention, and splits complex logic into smaller, simpler steps.
I'd like to recommend some improvements to your solution:
You're using Spring. You should not create any injected beans using new. Let Spring instantiate and manage those beans for you.
Use the #Repository annotation to mark your persistence class.
Make your repository class interface based.
Don't embed "Mongo" into the class name. You happen to be using Mongo as your persistence provider now, but you may change your mind later. Don't reveal implementation information in your class names - hide it.
The Controller is part of the UI. It uses repositories and/or services to fulfill use cases. It's perfectly correct to use Spring to inject the repository into the Controller.
I'd recommend that you use Spring Boot, an opinionated version of Spring. Have a look at their guides to learn how to use it properly.

How to retrieve common values (IpAddress, TenantId) in GenericDao?

We are using the Play! framework for HTTP sessions.
tenantId and ipAddress are columns that are common across multiple tables.
When the user is logged in, we are storing the tenantId in HttpContextSession
Whenever we require the ip address of the user we are using Http.Context.current().request().remoteAddress() to store the ip address.
We have huge set of queries written and now we want to save or query in a generic way for tenantId.
All the queries goes via GenericDao
Can we use the following in GenericDao to get tenant Id so that we can append in all queries?
Http.Context.session().get("tenantId");
what would be the best approach to save or retrieve these details?
Thanks.
You don't want your DAO to have to depend on presentation layer things like an HTTP session. I would recommend an abstraction to hide these details.
Create an interface called TenantIdProvider and inject it into your DAO. It would look something like this:
public interface TenantIdProvider
{
String getTenantId();
}
Then create an implementation called HttpSessionTenantIdProvider.
class HttpSessionTenantIdProvider implements TenantIdProvider
{
#Override
public String getTenantId()
{
return Http.Context.session().get("tenantId");
}
}
Now your GenericDAO can have a reference to TenantIdProvider and every query that needs the tenantId can get it through the TenantIdProvider and not have any dependency on the play framework or any other presentation layer that you use.
This really becomes important if you end up having scheduled jobs that run and send notifications or some other task, and they use this DAO. If this DAO depended on an HTTP session it would not be possible. Your job app could create a TenantIdProvider that just returned "system" or something like that.

Using findBy in transactional context

Given:
controller PersonController with a #Transactional action save
service PersonService with a method populateProperties(PersonInstance) being called from the controller action
I'd like to populate personInstance properties based on some data already persisted in the database, like this:
def personLookupData = PersonLookupData.findByUsername(personInstance.username)
personInstance.firstName = personLookupData.firstName
The findByUsername method flushes the hibernate session and in order to avoid it (because it has been giving me problems described here), I do this:
def personLookupData = PersonLookupData.withNewSession { PersonLookupData.findByUsername(personInstance.username) }
personInstance.firstName = personLookupData.firstName
This does what I want (lets me use findBy without flushing the session), and this is fine when there is only a couple of findBys to use, but given a deeper call stack (in terms of services) and more database lookups in different places, using withNewSession everywhere becomes a bit ugly.
Apart from making a PersonLookupService which will collect all the required data in one withNewTransaction block and return it, is there any other nice (groovy) way of doing this?
I think you should move #Transactional from PersonControlller to PersonService.
If you have more service calls to include in the same transaction, you need to use a Transaction boundary gateway, that's marked as #Transactional and calls all services you need for the current business case.
It's not the responsibility of the MVC components to control transactions. The transactions boundary are handled by the service layer.

Using Aspect Oriented Programming for user authentification in Java?

I like to add an user authentification to my REST webservice (Guice + Jersey).
I first wanted to solve the authentification with the Google Guice method interceptions. For example:
#Path("user")
public class User {
#OnlyAdmin
#Post
public void addUser(String apiKey) {
}
}
But unfortunately Guice only support AOP for classes with a no-argument constructors.
Is it generally a good idea to use AOP for user authentification?
Are there other frameworks to build an user authentification?
Edit: Framework is maybe the wrong term. I'm only looking for a way to inject some code in every annotated method and this code should check the parameters of the method
The only important point for AOP to work in your case is that your classes get created by Guice.
If you have constructors with arguments, ensure that they are injectable (directly or with assisted injection).
It wouldn't be AOP but you could inject a current user role bound to the request scope wherever the user needed to be checked and use either method intercepts or explicit logic to check that the right user class is performing some action.

Categories

Resources