I have a Spring MVC application using JPA 2. All the controllers are annotated with #Transactional at the class level.
Is it possible to keep that annotation at the class level and simply override it with another #Transactional annotation at the method level? I have one method I'd like to make SERIALIZABLE.
You can add multiple transaction managers by adding qualifiers to distinguish which one that should be used, provided that they have been configured:
#Transactional("global")
public class SomeService {
public void methodThatUsesTheGlobalTxManager() {
// ...
}
#Transactional("special")
public void methodThatUsesTheSpecialTxManager() {
// ...
}
}
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 have a service-client project which is in normal spring application , not spring boot .its used for mainly logging related things.which contains Interceptor , loggingservice impl class and some model classes for logging. I have added this module as a dependency to main application in pom.xml.and i was able to inject and use the loggingService beans within the service layers of the main application.
Am getting NullPointerException while auto-wiring loggingService within the interceptor .The bean is not available within the interceptor.but like i said it can be injected and used within the main application.
Also am not able to read properties using #Value within the interceptor.
This is my Interceptor class .
#Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
#Autowired
LoggingService loggingService;
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
loggingService.info("Am in prehandle");
return true;
}
}
This is my configuration class where i register the interceptor with the main application
#Component
public class LoggingConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getLoginInterceptor());
}
#Bean
public LoggingInterceptor getLoginInterceptor() {
return new LoggingInterceptor();
}
}
My question is almost similar to this post Cannot Autowire Service in HandlerInterceptorAdapter , but its different like am referring the interceptor from another module , and like they suggested i tried to create the bean from the application.
But the issues am facing right now is
getting NullPointerException while injecting loggingService within interceptor, but its working in main application
#Value annotation also return null, not able to read from properties
You have 2 possible solutions.
Mark your LoggingConfig as #Configuration instead of #Copmponent
Inject the LoggingInterceptor instead of referencing the #Bean method
Option 1: LoggingConfig as #Configuration
Your LoggingConfig is marked as an #Component whereas it should be marked as an #Configuration. The difference is that whilst it is allowed to have an #Bean method on an #Component it operates in a so-called lite mode. Meaning you cannot use method references to get the instance of a bean (this is due to no special proxy being created). This will lead to just a new instance of the LoggingInterceptor being created but it isn't a bean.
So in short what you are doing is equivalent to registry.addInterceptor(new LoggingInterceptor()); which just creates an instance without Spring knowing about it.
When marking the LoggingConfig as an #Configuration a special proxy will be created which will make the LoggingInterceptor a proper singleton bean, due to the method call being intercepted. This will register the bean in Spring and you will be able call the method.
NOTE: You actually endup with 2 instances of the LoggingInterceptor one due to the #Component on it the other through the #Bean. Remove the #Component.
Option 2: Inject the LoggingInterceptor.
As your LoggingInterceptor is marked as an #Component Spring will already create an instance (you actually have 2 instances of it created in your current setup). This instance you can inject into your LoggingConfig.
#Component
public class LoggingConfig implements WebMvcConfigurer {
private LoggingInterceptor loggingInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor);
}
}
With this you can remove the #Bean method as you will get the proper one injected into your LoggingConfig class. The class can also remain an #Component in this case. Although I would recommend using #Configuration as to also properly stereotype it.
NOTE: If you are on a recent Spring version you can use #Configuration(proxyBeanMethods=false). This will make a lite-configuration (just like an #Component) but it is still marked properly as a configuration class.
I have the following bean / constructor definitions:
#Configuration
class Configuration {
#Bean
public List<Something> getSomethings(MyFancyStuff stuff, #Autowired Bar bar) {
//...
}
}
#Component
class SomeOtherThing {
public SomeOtherThing(MyFancyStuff stuff, #Autowired Bar bar) {
//...
}
}
Is it possible to extends dependency resolution to provide a custom resolver when a specific class or annotation is found for a given parameter? I looked at PropertyPlaceholderConfigurer and InstantiationAwareBeanPostProcessor but nothing seemed to help me write my own value provider.
As a context: I implemented a custom scope which creates many instances of a given bean for each configuration object it has. I want to pass this configuration object to the bean-creation-process of said scope without adding it to the application context. I don't want to add it to the application context because it is an object which no other object should be able to obtain through dependency injection. I need to extend the DI-process of spring because I want to support field injection, constructor injection and bean factory-methods like the shown getSomethings
note: this is not about automatic value conversion of SpringMVC request parameters.
You can use #Conditional Annotation
#Bean(name="dataSource")
#Conditional(value=DevCondition.class)
public Util getSource1() {
return new DevUtil();
}
#Bean(name="dataSource")
#Conditional(ProdCondition.class)
public Util getSource2() {
return new ProdUtil();
}
you can also create bean based on property value using #Profile
In below code , when methodInner() is called from within methodOuter, should be under transaction bounds. But it is not.
But when methodInner() is called directly from MyController class , it is bound by transaction. Any explanations?
This is controller class.
#Controller
public class MyController {
#Autowired
#Qualifier("abcService")
private MyService serviceObj;
public void anymethod() {
// below call cause exception from methodInner as no transaction exists
serviceObj.methodOuter();
}
}
This is service class.
#Service("abcService")
public class MyService {
public void methodOuter() {
methodInner();
}
#Transactional
public void methodInner() {
.....
//does db operation.
.....
}
}
Spring uses Java proxies by default to wrap beans and implement annotated behavior. When doing calls within a service you bypass proxy and run method directly, so annotated behavior is not triggered.
Possible solutions:
Move all #Transactional code to separate service and always do calls to transactional methods from outside
Use AspectJ and weaving to trigger annotated behavior even within a service
Add #Transactional to methodOuter() and it works.
Suppose I have this:
#Transactional(rollbackFor = NotificationException.class)
public interface PersonManagerService {
public void addPerson(Person person);
}
and an implementation:
public class PersonManagerServiceImpl implements PersonManagerService {
public OtherService otherService;
public void addPerson(Person person) {
// stuff
}
// getter and setter for otherService
}
How would I go about mocking the otherService dependency while still having the addPerson method hit the database?
My scenario is that I want to test that a particular exception causes a rollback of the saving of the person that is being added. This exception would come from the OtherService class, which I don't want to call the real version of. I am currently using Spring Transaction annotations so I have a test like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {various locations})
public class Test() {
#Autowired
PersonManagerService service;
#Test
public void test() {
// how to call setOtherService so it can be a mock?
}
If I try to cast the auto wired bean, I get an IllegalArgumentException because it is a proxy. If I made the Impl not use an interface, I could use CGLIB but I don't want to do that. If I create the impl programmatically, then it's not tied into the transaction flow. What other options do I have?
There are various ways you can tackle this program (from best to worst):
take advantage of #Profiles - in Spring 3.1 you can associate profile name with every bean. When you are starting an application context you provide active profiles and only beans without any profile associated or with profile matching provided will be instantiated. This is a very powerful mechanism.
#Profile("prd")
public class PersonManagerServiceImpl implements PersonManagerService
//...
#Profile("test")
public class PersonManagerServiceMock implements PersonManagerService
//...
#ContextConfiguration
#ActiveProfiles(value = "test")
public class Test {
use primary or #Primary - if you are autowiring otherService in PersonManagerServiceImpl you can define a second mock bean with primary="true" attribute or #Primary annotation. Spring will prefer primary beans when autowiring.
unwrap transactional proxy (see: Is it possible to unproxy a Spring bean? and Mocking a property of a CGLIB proxied service not working) to access setter. A bit hacky, but works for others