Using HttpServletRequest in Spring Service Layer - java

Environment :
Spring MVC 3
Angular JS
Tomcat 6
Issue :
We are migrating a legacy application from struts2 to spring MVC REST with angular JS as UI.
This is a typical SPA.
The typical application flow is : Angular JS + Spring REST controller + Servicelayer
The business logic in struts2 actions is moved to service classes.
My question is - What is the correct way to make HttpServetRequest object available to Service classes in Spring ?
Two options available are :
1)Pass HttpServletRequest to Spring MVC controller method. Pass the same HttpServetRequest to Spring service layer.
But this will result in HttpServletRequest being part of Service interface like -
public ProductDto getProductDetails(HttpServletRequest req,int productId)
Is this a correct way ? Can HttpServletRequest be part of Service interface ?
2)Use Spring provided API :
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Please guide on this ?

In addition to those mentioned options, you can introduce a class or another abstraction into your service layer, then populate it with the required parts of the HttpServletRequest and use that abstraction inside the Service Layer.
For example (Borrowed from Spring Data), Suppose you want to access to page, size and sort and user related query strings from the HttpServletRequest. Instead of passing the request to the service layer methods, you can also encapsulate those parameters into an abstraction, say, Pageable or UserFilterCriteria:
public interface Pageable {
int page();
int size();
List<Sort> sorts();
}
Then instead of passing the HttpServletRequest to the service layer:
public interface UsersService {
List<User> filterUsers(HttpServletRequest request);
}
You can pass those new abstractions:
public interface UsersService {
List<User> filterUsers(UserFilterCriteria criteria, Pageable pageable);
}
This way you can easily define abstractions in the same level of abstraction as your service layer.

You should rather not make HttpServletRequest/-Response be part of your service-layer, as HttpServletRequest/-Response are classes specific to your user interface/view technology.
Introducing them to your service layer will make your service layer depend on the technology used for the user interface, thus making it harder to change the UI/View technology later.

Related

How to write a Spring Cloud Contract contract for endpoint that uses #ModelAttribute parameter?

This is the endpoint I'm trying to write a SCC contract for. It consumes form data as a DTO and processes it.
PostMapping(value = "/bar/process", consumes = MULTIPART_FORM_DATA_VALUE)
public List<Foo> processBar(
#ModelAttribute("data") BarDto barDto) {
return barService.processBar(barDto);
}
I cannot figure out how to write a groovy contract for this endpoint. I know how to write contract tests for controllers that use multipart form data using #RequestPart annotation, but here - I'm lost.
Can you even use CC with Spring MVC elements?
I'm using SCC version 2.2.7.

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 return a subset of object properties from a Spring Boot restful GET call?

Newbie question...
I'm building my first Spring Boot restful service and want to support a GET call that returns a collection of entities. like:
/api/customers/
However, for certain consumers -like a list page in a web UI - they would only need a subset of the customer entity properties.
I'm thinking that I could add request parameters to my GET call to set the consumers specific field requirements, like
/api/customers/?fields=id,name,address
But what's the best way of implementing this inside the Java restful controller?
Currently in my rest controller the 'GET' is request mapped to a Java method, like
#RequestMapping(value="/", method= RequestMethod.GET)
public Customer[] getList() {
Customer[] anArray = new Customer[];
....
return anArray;
}
Is it possible to somehow intervene with the default Java to Json response body translation so that only the required properties are included?
TIA
Adding fields parameter is a good idea, best practice according to http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#limiting-fields
How to leave fields out?
1) Set them to null, possibly in a dedicated output class annotated with #JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
Or
2) Use SimpleBeanPropertyFilter See a good step by step tutorial here 5. Ignore Fields Using Filters

Why we use service classes in spring hibernate integration

I want to know the use of service classes in J2EE.
I have 2 projects.
One is in spring hibernate integration.That project contain DAO,MODEL,SERVICE and CONTROLLER.Within that The request is access by the controller and send to the values to the dao class through the service class.
2nd project contain only BEAN,CONTROLLER and DERIVED classes.Within that the request is access by the controller and send the values directly to the derived class.Query is written in this derived class.
I want to know the difference between these two projects. Why we use service class ?
in my experience, service class contains all business , calculate, logic
for example in login module :
base on MVC pattern
Model class (DAO,MODEL is call model) : User, UserDAO
Controller : UserController
View : LoginPage
That's doesn't mean we cannot create another class like Service
we can have UserBusinessthis class contain all method, logic realted to User like validateUserLogin ... etc
application may work like :
User access LoginPageinput value and submit => UserController=> UserBusiness=> UserDAO
we need divide to easy handle and maintain
In spring we have some annotation like
#Business
#Repository
#Controller
that is a maker spring will create a object , we no need to using "new" keyword.
Controllers: are used to just delegating the calls, meaning once the request arrive on controller it will forward it to relative service
Services: Service are develop to write the business logic in general.
Dao: Data transfer object, which intend to deal with the DTO's
So, Briefly, when Spring MVC receive a call. I will lend to controller, controller than redirects it to respective service. Service performs business login if any on the api call and than delegated data updation to DAO layer.

Spring MVC Domain Object handling Best Practice

Lets assume a simple Spring MVC Controller that receives the ID of a domain object. The Controller should call a service that should do something with that domain object.
Where do you "convert" the ID of the domain object into the domain object by loading it from the database? This should not be done by the Controller. So the service method interface has to use accept the ID of the domain object instead of the domain object itself. But the interface of the service would be nicer if it takes the domain object as a parameter.
What are your thoughts about this common use case? How do you solve this?
The controller should pass the id down into the service layer and then get back whatever is needed to render the rest of the HTTP response.
So -
Map<String,Object> doGet (#RequestParam("id") int id) {
return serviceLayer.getStuffByDomainObjectId(id);
}
Anything else is just going to be polluting the web layer, which shouldn't care at all about persistence. The entire purpose of the service layer is to get domain objects and tell them to perform their business logic. So, a database call should reside in the service layer as such -
public Map<String,Object> getStuffByDomainObjectId(int id) {
DomainObject domainObject = dao.getDomainObjectById(id);
domainObject.businessLogicMethod();
return domainObject.map();
}
in a project of mine I used the service layer:
class ProductService {
void removeById(long id);
}
I think this would depend on whether the service is remote or local. As a rule I try to pass IDs where possible to remote services but prefer objects for local ones.
The reasoning behind this is that it reduces network traffic by only sending what is absolutely necessary to remote services and prevents multiple calls to DAOs for local services (although with Hibernate caching this might be a mute point for local services).

Categories

Resources