If I have a Spring webapp, with an endpoint like so:
#Autowired
UnpublishedStuffFactory unpublishedStuffFactory;
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
#ResponseBody
public OutputStuff update(#RequestBody Stuff stuff, #PathVariable String id) {
UnpublishedStuff uStuff = unpublishedStuffFactory.get(stuff);
//handle the request
}
UnpublishedStuffFactory.java:
#Component
public class UnpublishedStuffFactory {
#Autowired
//some autowired beans
public UnpublishedStuff get(Stuff stuff) {
return new UnpublishedStuff(stuff, /*some autowired beans*/);
}
}
So Stuff is my domain object (simple POJO). OutputStuff is something I generate (some metadata etc) and return if update was ok.
It all works fine, however I would like spring to automatically execute this factory method when request comes in, and inject UnpublishedStuff to the update method, instead of injecting Stuff.
Basically UnpublishedStuff is kind of a decorator around Stuff that adds functionality via other autowired beans (from the factory) to validate, publish etc to Stuff (I do not want this functionality in Stuff, I want it to stay a basic POJO, hence the decorator).
Is there a way to do this? Or maybe there is a better approach to this stuff?
Thanks for help :)
Related
I am writing a small CRUD in Spring and Java. And I want to use a separate file for writing logic, this is very convenient for me, I did this when developing with NestJS. I have a few questions, is it correct to do this in Spring, or should I do everything inside a function in the controller. And if I write logic in a separate file, I should mark the logic class as #Component and the functions inside it as #Bean, right? I am new to Spring and as I understand it, I have to do this in order for the application to work correctly and my functions to be in the application context.
AuthLogic.java
#Component
public class AuthLogic {
#Bean
public void register() {
// code ...
}
}
AuthController.java
#RestController
public class AuthController {
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
you can mark your logic class with #Service and use that for example you can make a AuthService and use it like
#Service
public class AuthService{
public returnType login(){
//Logic
}
}
and use this like
#RestController
public class AuthController {
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
authService.login();
}
}
You can write your business logic in a new separate file at service layer.
Suppose you name it as AuthService and you mark it with annotation #Service.
#Service
public class AuthService{
}
You can then Autowire it in your controller class.
#RestController
public class AuthController {
#Autowired
AuthService authService;
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public void register(#Valid #RequestBody UserDTO newUser) {
// here I call the register function from AuthLogic
}
}
Using separate files, or classes more importantly, is very recommended in Spring, and I assume most other languages.
The #Bean annotation on AuthLogic.java is unneeded and I think may cause startup or compilation errors.
I would change the name of AuthLogic to AuthLogicImpl, create an interface named AuthLogic with the method signature void register(), and have AuthLogicImpl implement AuthLogic. Then you can create a constructor for AuthController which accepts and AuthLogic parameter and sets it to a private field (note using the interface not the implementation in the constructor).
At the core of Spring is the IoC container. This container holds "beans" that can be injected or autowired into other beans. These beans are an instance of their class and can be used by other beans. Remember Spring uses the singleton pattern, so your beans should be stateless. This allows Spring to handle the application startup for you, so you don't need to write a ton of code creating all the different services/classes and wiring them together, it's all automagically done for you.
There are two key annoitations that you appear to be confused about:
#Component Putting this above a class will create an instance of that class (a bean) and put it into the IoC container. Other beans can access this by accepting the original beans interface in its constructor. So if I put #Component above my class FooImpl which implements Foo, then I can create a class, BarImpl with the constructor public BarImpl(Foo foo) {this.foo = foo} and BarImpl can use any public method of Foo (which will use FooImpl's implementation).
#Bean this is to be put on a method of a class that is annotated with #Configuration. This tells Spring that this method should be run at startup, and this method will return a bean that Spring should add to the IoC container. This is a popular way of configuring a bean that requires some parameters, such as the bean that manages the connection to a third party service or datastore, especially when that there is a little bit of logic that needs to go into creating the bean.
Note that the above is very broad, and there are some specifics if you need to dig deep into the spring framework, so there will be more clarification in the Spring documentation or you dig into some established Spring project. However it should suffice to answer the broad question of what is going on with #Component and #Bean.
There is no specific layout or code structure for Spring Boot Projects. However, there are some best practices followed by developers that will help us too. You can divide your project into layers like service layer, entity layer, and repository layer.
We use the entity layer to write all model and POJO classes. We annotate them with #Entity.
We use #Repository to indicate that this is a repository interface that is used to do some basic CRUD operations.
Sidenote:- You don't have to write #Repository for classes that implement or interfaces that extends Repository interfaces provided by Spring Boot framework.
We use #Service to say that this is the service class where your all business logic will be present.
We use the controller layer to receive HTTP requests and send back HTTP Responses or views.
You can learn and understand more from here
You can refer to this Image to understand the structure
project structure
I love dependency injection frameworks and how they allow me to request the one object everything starts with. All the wiring is made on the first request for that "master" object.
However, there are objects that should be created during runtime, e.g. based on user input. And sometimes those newly created objects should be shared among other objects created by the framework.
My current approach is to have "uninitialized" objects injected by the framework. During runtime I set up the object with setter methods as soon as possible.
What I don't like with this approach is that the setter methods are really invoked only once and should then never be touched again. This prevents me from declaring the fields as final. I don't now how to create the object not before all necessary information is available without losing all the benefits from the DI framework.
I'm new to DI. Are there any good patterns for this?
Example:
// The service is used through out the application
interface Service {
makeRequest()
}
What I want to do after user typed in credentials:
new ConcreteService(username, password)
// but now I need to inject the concrete servive manually everywhere I need it!
What I'm currently doing:
interface Service {
makeRequest()
setCredentials(username, password)
}
// service can be injected by framework, but I don't like setter methods
// that much (and they can pollute the interface)
Most of my experience with dependency injection is with C# but I believe the concept remains the same no matter what language.
What I understand from the original poster is that he's trying to "persist" information within the dependency injection container in order to retrieve the information at a later time.
The problem with this approach is that, in a multi-threaded scenario, there's the possibility that the dependency that you are using to persist information has its values overwritten by another thread. This can happen because the dependency injection container usually holds a single instance of the object which is returned to you whenever you need it. Therefore, you need to make sure that your design is thread safe.
In my experience, using the dependency injection container to maintain state is bad.
What you register in your dependency injection container are the objects that provide a "service" and that don't maintain any state.
Objects that you use to hold information are usually business objects. These business objects should just be instantiated with "new" (without the dependency injection container), populate them in the usual manner (with setters or initialization method or constructor) and just be passed on as part of the signature of the operations that your services expose.
Note: You can register your dependency as "transient" which would tell the dependency injection container to return a new instance every time you ask for the dependency. This would avoid the need to use the "new" keyword explicitly and give you more control when writing unit tests with a mocking framework.
Hope this helps!
One way you could do it would be to use a factory.
For example, say you had this class...
public class UserBean {
private int userId;
private UserService userService;
// other resources / dependency fields etc
public UserBean(int userId, UserService userService, ...other dependencies...) {
this.userService = userService;
this.userId = userId;
this.... = ...
}
// ...getter for userId maybe etc...
// Some method that uses the user's data AND the component/service you want to inject from Spring...
public void incrementHitCount() {
userService.incrementHitCount(userId);
}
}
...where "userService" is something you want that is managed by the IoC container. If you then have a component that needs to create one of these, e.g....
#Component
public class UserHitCountIncrementerThing {
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = new UserBean(userId, /* need dependencies here! */);
...do stuff...
}
}
You could just #Autowire in all of the services to this bean, or you could create a factory and just #Autowire one, for example...
#Component
public class UserBeanFactory {
#Autowired
private UserService userService
//...other #Autowired dependencies...
public UserBean createUser(int userId) {
return new UserBean(userService, ...etc..., userId);
}
}
Now just use this where you need it, e.g...
#Component
public class UserHitCountIncrementerThing {
#Autowired
private UserBeanFactory userFactory;
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = userFactory.createUser(userId);
...do stuff...
}
}
Is this what you were getting at?
Hope this helps.
I got Object coming in a REST web service controller's web method which is locally initialized.
#RequestMapping(method = RequestMethod.POST,value = "/test",headers="Accept=*/*")
public #ResponseBody ModelAndView computeDetails(#RequestBody RequestObj reqObj, ModelMap model) {
System.out.println(reqObj.getcode());
return new ModelAndView("responsedetails", "object", reqObj);
}
This RequestObj object holds the key code to instantiate dependency using factory.
Different codes classes have been defined which implement BaseCode Interface.
How can I use factory method to instantiate particular code class based on code value coming in as BaseCode type in my service bean?
Any idea? Thanks in advance.
What I usually do in such cases is:
inject the factory into the controller using Spring's bean
create a method getBaseCode(String code) in the factory (please note: String here stands for code type, so use the actual code type if not String
make getBaseCode returning the BaseCode interface while constructing the real implementation
supposing you have an execute method in BaseCode, use the getBaseCode method into the controller to get the real collaborator and then call the execute method to perform the actual action
Ignoring the first point (which I think you can easily looking at any Spring tutorial) the factory will be something like
public class BaseCodeFactory {
public BaseCode getBaseCode(String code) {
if(code.equals("something")) return new ThisBaseCodeImpl();
else //and so on
}
}
while computeDetails becomes similar to:
#RequestMapping(method = RequestMethod.POST,value = "/test",headers="Accept=*/*")
public #ResponseBody ModelAndView computeDetails(#RequestBody RequestObj reqObj, ModelMap model) {
//...
factory.getBaseCode(reqObj.getcode()).execute();
//...
}
As a side note, I will not go for names like the one I choose here, I suggest you to look for something more significative in your domain (BaseCode has no meaning for example), take this snippets just as a directive.
Base on OP comment. If you have ThisBaseCodeImpl which makes use of other Spring bean you can
annotate it with #Configurable so, when you use new ThisBaseCodeImpl(/*args if you like*/) its bean are instantiated by Spring. I don't personally like this solution since, in my opinion, it pollutes the code with hidden Spring's bean. On the other hand is quite flexible, since it allows you to manage both runtime constructor arguments and Spring beans
add ThisBaseCodeImpl to the Spring context and change the factory, so that a collaborator for ThisBaseCodeImpl is injected into it.
1st point example:
#Configurable
public class ThisBaseCodeImpl {
#Resource
private Bean bean;
}
2nd point example:
public class BaseCodeFactory {
#Resource
ThisBaseCodeImpl thisBaseCodeImpl;
public BaseCode getBaseCode(String code) {
if(code.equals("something")) return thisBaseCodeImpl;
else //and so on
}
}
I'm not sure if I understood your problem well, but in general spring dependencies have nothing to do here. Just write custom Factory class and return BaseCode implemetation depending on the reqObj.getcode().
I did it this way -
Make your factory as ServletContextAware in a way to get the currentContext. And define getInstance method as
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
ctx.getBean(classNameToBeInstantiated);
Define your bean's inheritance in spring context so that Spring injects its dependencies.
I am trying to implement the registration controller for a Rest API. I have read about where to place #Transactional quite a bit. (Not at DAO level but at the services maybe orchestrated). In my use case I want not only services but also a hibernate validation to use the same transaction.
This is the code of the controller:
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
#Transactional
public DefaultResponse register(#Valid RegisterIO registerIO, BindingResult errors) {
DefaultResponse result = new DefaultResponse();
if (errors.hasErrors()) {
result.addErrors(errors);
} else {
userService.register(registerIO);
}
return result;
}
I have written an custom contraint annotation, which validates an attribute of the parameter registerIO. Both, this validator and userService.register(registerIO); access the database (check if the email address is already in use).
Therefore I want both methods use the same Hibernate session and transaction.
This approach results in the following exception:
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)
The problem is the #Transactional annotation. When I place this annotation at the methods witch call the database everything works find but two transactions are startet. I suspect that when i place it at the register Method the hibernate validation is performed before #Transactional starts the transaction for this method.
I developed the following functional workaround but I am not happy with it. This codes does not use the #Valid annotation but calls the validator by itself:
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
#Transactional
public DefaultResponse register( RegisterIO registerIO, BindingResult errors) {
DefaultResponse result = new DefaultResponse();
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();
Set<ConstraintViolation<RegisterIO>> valResult = validator.validate(registerIO);
I try to summarise my question:
Using Spring MVC and Hibernate-Validation together with #Valid and #Transactional, how is it possible to encapsulate the whole request into one transaction?
Thank you :)
Your workaround could be improved by using a single Validator and injecting it intp the controller. Have you tried:
#Autowired
private Validator validator;
This way you skip the overhead of creating the validator on each request.
You should also be careful with race conditions. While you are checking the database whether a given email exists another request can create this record, so that you still get an exception at the time you insert the data.
I'd like to be able to have the following:
#Controller
public class MyController {
#RequestMapping(value="/someurl", method=RequestMethod.GET)
#PreProcess
#PostProcess
public String doStuff(ModelMap map) {
//do stuff
return "someurl";
}
}
The #PreProcess and #PostProcess are arbitrarily named Annotations.
I've been looking for a working example of this but I can't find any. I've looked at AOP and the use of the #Aspect annotation but I found it quite complex. A working example of what I'm trying to do would be great.
I've sampled Spring Security in the past but this isn't quite what I need because I need the processing to be custom, pretty much anything I want.
I know that this functionality is available in .Net MVC. Hoping it's available in Spring also.
Any help or pointers really appreciated.
You can annotate a method with #ModelAttribute to execute a method before a controller method. Or use an interceptor
Example with #ModelAttribute
#Controller
public class MyController {
#RequestMapping(value="/someurl", method=RequestMethod.GET)
public String doStuff(#ModelAttribute("something") Something something, ModelMap map) {
//do stuff
// here you can do what you want with something it has been provided to you in the method parameters
return "someurl";
}
#ModelAttribute("something")
public Something something() {
// do what you need
return new Something();
}
}
The something() method will be called before every method having a #RequestMapping annotation, thus before the doStuff() method.