I am using spring 5.2.8
I am using #Autowired to get create the Bean. But i am getting NullPointer when I used this bean
configuration
#Configuration
#Primary
#ComponentScan(basePackages = {"com.try.appli"})
#EnableJpaRepositories(basePackages = "com.tryappli.persistence")
#EnableTransactionManagement
public class AppliConfiguration {
...
My component in package com.try.appli
#Component
#Primary
public class Mycomponent extends MycomponentAbstract {
#Autowired
MyService service
public handle()
String data ="{data to update}";
service.update(data);
service :
#Service
public MyService {
#Autowired
private RestOperations resoperation;
public void update(dataToUpdate) {
restOperations.put("url", dataToUpdate);
}
....
I also tried to put the annotation on the implementation but without success
In web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Related
I have a spring boot app that I want to handle both rest calls and websockets. In my RestController I am able to define an instance of my GameUnitService as autowired, and it works as expected. ie: Gets populated and I can use it.
#Autowired private GameUnitService gameUnitService;
But when I try to autowire the above service in my websocket config, I get the error Could not autowire. No beans of 'GameUnitService' type found.. No error on the ApplicationContext.
However when I run the app after I remove the autowired from GameUnitService, the appContext is null when McpWebSocketConfig gets constructed.
#Configuration
#EnableWebSocket
public class McpWebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(McpWebSocketConfig.class);
#Autowired private GameUnitService gameUnitService; //error: Could not autowire
#Autowired private ApplicationContext appContext; //this will end up null
public McpWebSocketConfig() {
//appContext is null
}
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new McpWebSocketHandler(), "/socket").setAllowedOrigins("*");
registry.addHandler(new McpWebSocketHandler(), "/").setAllowedOrigins("*");
}
I had also tried moving the GameUnitService into the handler, and while the bean error was no longer present, the gameUnitService is null.
public class McpWebSocketHandler extends AbstractWebSocketHandler {
#Autowired
private GameUnitService gameUnitService;
public McpWebSocketHandler() {
// gameUnitService is null
}
To find the bean (You will need the bean of GameUnitService for Autowire), you need to enable the behavior to scan your classpath which spring does not do by default.
#ComponentScan is the annotation to scan for components declared in your code . by default, #ComponentScan only scans the package and all the sub-packages of its annotated class.
This means you need to tell the #ComponentScan to scan different packages,
preferably your root package .
So you will need an additional annotation.
#ComponentScan(basePackageClasses = ApplicationLauncher.class)
ApplicationLauncher is the class annotated with #SpringBootApplication
Change your configuration class to read like so:
#Configuration
#EnableWebSocket
#ComponentScan(basePackageClasses = ApplicationLauncher.class)
public class McpWebSocketConfig implements WebSocketConfigurer {
private static final Logger log = LoggerFactory.getLogger(McpWebSocketConfig.class);
#Autowired private GameUnitService gameUnitService; //error: Could not autowire
#Autowired private ApplicationContext appContext; //this will end up null
public McpWebSocketConfig() {
//appContext is null
}
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new McpWebSocketHandler(), "/socket").setAllowedOrigins("*");
registry.addHandler(new McpWebSocketHandler(), "/").setAllowedOrigins("*");
}
I have the following configuration class:
#Configuration
public class AppConfig {
#Value("${my.value}"
private String myValue;
// The rest of the code
}
And it is working fine and my.value from properties is assigned to myValue.
But if I add #EnableAsync annotation to this class, it is not working.
#Configuration
#EnableAsync
public class AppConfig {
#Value("${my.value}"
private String myValue;
// The rest of the code
}
This is the error:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException
It can be fixed by adding PropertySourcesPlaceholderConfigurer bean in the class.
#Configuration
#EnableAsync
public class AppConfig {
#Value("${my.value}"
private String myValue;
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
// The rest of the code
}
Can someone explain me why is it needed to instantiate PropertySourcesPlaceholderConfigurer bean when having #EnableAsync annotation?
I have a web app with JSF 2.2, Spring 4, ang Hibernate Integration. When I try to inject a Spring Service with ManagedProperty in a ManagedBean I have a Nullpointer Exception:
#ManagedBean
#ViewScoped
public class SuperAdminNuevasAppBean {
#ManagedProperty(value = "#{appService}")
private AppService appService;
//Code
}
AppService is an interface:
public interface AppService {
public abstract void persist(App transientInstance);
public abstract void remove(App persistentInstance);
public abstract App merge(App detachedInstance);
//
}
This is the implementation:
#Service
public class AppServiceImpl implements AppService {
#Autowired
private AppDAO appDAO;
#Autowired
private EdificioDAO edificioDAO;
#Override
#Transactional
public void persist(App transientInstance) {
// TODO Auto-generated method stub
appDAO.persist(transientInstance);
}
//More code...
If I put
#ManagedProperty(value = "#{appServiceImpl}")
private AppService appService;
everything works ok.
I have the getters and setters, the org.springframework.web.jsf.el.SpringBeanFacesELResolver in faces-config, the org.springframework.web.context.ContextLoaderListener and org.springframework.web.context.request.RequestContextListener in web.xml. Is this the right behavior?
I thought it was best practice to put the #Transactional annotation on the service layer classes and not on the controllers (see f.e. Why we shouldn't make a Spring MVC controller #Transactional?). But this not working on my Spring Boot application. Why is that?
The registerAction method in the controller (see code below) performs multiple service calls. When f.e. the mailService.sendActivationMail(...) fails, I want to rollback the inserted user from the userService.registerUser(...) call. Do I need to put the #Transactional annotation on the controller class or not?
My Spring Boot application correctly uses transactions when the #Transactional annotation is set on the controller class:
AuthController.java
#RestController
#RequestMapping("/api/auth")
#Transactional
public class AuthController {
#Autowired
private UserService userService;
#Autowired
private ProfileService profileService;
#Autowired
private MailService mailService;
#RequestMapping(path = "register", method = RequestMethod.POST)
public Profile registerAction(#Valid #RequestBody Registration registration) {
ApiUser user = userService.registerUser(registration);
Profile profile = profileService.createProfile(user, registration);
mailService.sendActivationMail(user);
return profile;
}
}
but transactions don't work when the #Transactional annotation is set on the Service classes instead (and not on the controller):
UserService.java
#Service
#Transactional
public class UserService {
#Autowired
private ApiUserRepository userRepository;
public ApiUser registerUser(Registration registration) {
...
userRepository.save(user);
...
}
}
My configuration classes:
SpringApiApplication.java
#SpringBootApplication
public class SpringApiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringApiCommonApplication.class, args);
}
}
ApiConfiguration.java
#Configuration
#EnableJpaAuditing
#EnableTransactionManagement
public class ApiConfiguration {
#Autowired
private ApiProperties properties;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public UsernameCanonicalizer usernameCanonicalizer() {
return new UsernameCanonicalizer();
}
#Bean
public EmailCanonicalizer emailCanonicalizer() {
return new EmailCanonicalizer();
}
#Bean
public ApiTokenHandler activationTokenHandler() {
return new StandardApiTokenHandler(properties.getActivationTokenDuration());
}
}
#M.Deinum got me on the right track. Spring (boot) doesn't automatically wrap your controller calls in a transaction like other frameworks do. So you have to either add a #Transactional annotation to your controller, or move the code from the controller class to a service class.
Moving the code from the controller class to a service class is the better thing to do since (amongst other things) makes the code better testable. So that's what I did.
AuthenticationService.java
#Service
public class AuthenticationService {
#Autowired
private UserManager userManager;
#Autowired
private ProfileManager profileManager;
#Autowired
private MailManager mailManager;
#Transactional
public Profile registerUser(Registration registration) {
ApiUser user = userManager.registerUser(registration);
Profile profile = profileManager.createProfile(user, registration);
mailManager.sendActivationMail(user);
return profile;
}
...
}
AuthController.java
#RestController
#RequestMapping("/api/auth")
public class AuthController {
#Autowired
private AuthenticationService authenticationService;
#RequestMapping(path = "register", method = RequestMethod.POST)
#ApiOperation(value = "Registers a user")
public Profile register(#Valid #RequestBody Registration registration) {
return authenticationService.registerUser(registration);
}
...
}
You can place the #Transactional annotation before an interface definition, a method on an interface, a class definition, or a public method on a class. However, the mere presence of the #Transactional annotation is not enough to activate the transactional behavior.
The #Transactional annotation is simply metadata that can be consumed by some runtime infrastructure that is #Transactional-aware and that can use the metadata to configure the appropriate beans with transactional behavior.
In the preceding example, the <tx:annotation-driven/> element switches on the transactional behavior.
// Below is the service class that we want to make transactional
#Transactional
public class DefaultEmployeeService implements EmployeeService {
void insertEmployee(Employee Employee);
void updateEmployee(Employee Employee);
}
XML Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" ...>
<!-- this is the service object that we want to make transactional -->
<bean id="employeeService" class="service.DefaultEmployeeService"/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- (this dependency is defined somewhere else) -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Some points that you can try:
Do all above mentioned configurations.
Remove #Transactional configuration from Controller.
Reference the Service object along with Transaction manager bean.
More Details: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html
In my project I've a DAO defined as a org.springframework.data.repository
#RepositoryRestResource(path = "/user")
public interface SymtUserDAO extends CrudRepository<User, Long>{
...
It works fine in controllers by #Autowired (Dependency Injection):
#Controller
public class ProveController {
#Autowired
private SymtUserDAO dao;
...
I need to use it in my custom UserDetailsManager but in here the dao is always null
public class SymtUserManager implements UserDetailsManager {
#Autowired
private SymtUserDAO dao;
I don't know if it matters but I instantiate my custom UserDetailManager in the AuthorizationServerConfigurerAdapter's constructor
/**
* This class is used to configure how our authorization server (the "/oauth/token" endpoint)
* validates client credentials.
*/
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
....
public OAuth2Config() throws Exception {
UserDetailsService svc = new SymtUserManager(...
Why my working DAO (test passed in the controller) doesn't work ( it is always null) in the UserDetailsManager? what I have to do to use the DAO ( repository ) also into the UserDetailsManager?
EDIT: zeroflagL is right. I updated answer according to comments.
Your SymtUserManager is not s spring bean. Therefore it's not created and handeled by Spring bean container. Therefore spring can't inject dependency there.
You can autowire it into OAuth2Config constructor and pass it as constructor parameter to SymtUserManager:
#Configuration
#EnableAuthorizationServer
#Order(Ordered.LOWEST_PRECEDENCE - 100)
protected static class OAuth2Config extends
AuthorizationServerConfigurerAdapter
{
private SymtUserDAO dao;
#Autowire
public OAuth2Config(SymtUserDAO dao) throws Exception {
UserDetailsService svc = new SymtUserManager(dao, ...