Spring boot application not identifying controller and repository beans - spring-boot

I have this project structure
com.demo.application
- DemoApplication.java
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
System.out.println("inside main");
SpringApplication.run(DemoApplication.class, args);
}
}
I have another package
com.demo.application.employee
- EmployeeController.java
- EmployeeInterface.java
- Employee.java (Entity Bean)
#Controller
#RequestMapping("/getAll")
public class EmployeeController {
#Autowired
EmployeeInterface empInterface;
public ModelAndView getEmployees() {
System.out.println("inside controller");
return new ModelAndView("employee", "employee", empInterface.findAll());
}
}
#Repository
public interface EmployeeInterface extends JpaRepository<Employee, Long>{
}
When i access the below URL i get 404. The reason is the Controller and Repository beans are not loaded.
http://localhost:8080/getAll
Any help?

Your getAll does not associated with any controller handler.
Add #RequestMapping to your getEmployees() method:
#RequestMapping
public ModelAndView getEmployees() {
But it's not very intuitive. You should annotated your controller with the base path and your method with specific path:
#Controller
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
EmployeeInterface empInterface;
#RequestMapping("/getAll")
public ModelAndView getEmployees() {
System.out.println("inside controller");
return new ModelAndView("employee", "employee", empInterface.findAll());
}
}
Now your URL looks like: localhost:8080/employee/getAll

Related

Spring JPA : REQUIRES_NEW propagation not working

I have the following scenario where I have one controller containing two functions (saveAudit and saveProduct). Each one persists an object,I would like to separate transactions between those functions.
throwed exception on saveProduct function should not rollback transaction on saveAudit function :
My repositories/ DAO :
public interface AuditRepository extends JpaRepository<Audit, String> {
}
public interface ProductRepository extends JpaRepository<Product, String> {
}
My controller:
#RestController
#Transactional
public class ProductController {
private final ProductreRepository productRepository;
private final Auditrepository auditRepository;
#Transactional(propagation=Propagation.REQUIRES_NEW)
void saveAudit()
{
auditRepository.saveAudit(Audit.builder().action("action1").build());
}
#PostMapping(ApiPaths.PRODUCTS)
#ResponseStatus(HttpStatus.CREATED)
public ProductDTO addNewProduct() {
ProductDTO res = productRepository.saveProduct(Product.builder().label("product1").build());
saveAudit();
int h=1/0; // => throw exception to rollback product creation
return res;
}
}
Logs:
Participating in existing transaction
its same class proxy will not work.
move below method to #Service class and inject in your controller or annotate #Transactional(propagation=Propagation.REQUIRES_NEW) in auditRepository.saveAudit
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void saveAudit()
{
auditRepository.saveAudit(Audit.builder().action("action1").build());
}

Why can't #Autowired a JPA repository - Spring boot + JPA

I'm giving this error:
Parameter 0 of constructor in x.microservice.module.business.application.BusinessCreator required a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=false)
Action:
Consider defining a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' in your configuration.
The controller:
#Slf4j
#RestController
public final class BusinessPostController {
#Autowired
private BusinessCreator creator;
#PostMapping(value = "/business")
public ResponseEntity create(#RequestBody Request request){
BusinessCreatorDto businessCreatorDto = new BusinessCreatorDto(IdentifierEpoch.generate(),request.getName());
return ResponseEntity.ok(
creator.create(businessCreatorDto)
);
}
}
The Application Layer:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}
In the Infrastructure layer
#Repository
public abstract class HibernateJpaRepository implements JpaRepository<Business, Long> {
}
The boot Application:
#EnableJpaRepositories
#SpringBootApplication
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
}
All dependencies are resolved and the others classes I believe that are irrellevant.
Any suggestions? Thank you very much
Probably, the error cause is HibernateJpaRepository - it has to be an interface that extends JpaRepository.
You could write your own Repository in a interface:
#Repository
public interface HibernateJpaRepository extends JpaRepository < Business, Long > {
}
Then your Class:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}

#Autowired annotation not working for one #Controller class and working for others

I have three #RestController classes, for two of them the #Autowired is injecting the bean, but for one it is not. I don't know what the issue is, as few hours ago the same code was working fine.
package com.learn.service;
package com.learn.service;
#Service
#Transactional
public class RoleService {
#Autowired
private RoleJpaRepository roleJpaRepository;
public List<Role> findAll(){
return roleJpaRepository.findAll();
}
}
the controller for Role
package com.learn.controller;
#RestController
#RequestMapping("/roles")
public class RoleController {
#Autowired
private RoleService roleService;
#RequestMapping(method = RequestMethod.GET)
private List<Role> findAll() {
System.out.println(roleService); // roleService is null here and NullPointerException is thrown from below method call.
return roleService.findAll();
}
}
Configuration class for Service
package com.learn.springConfig;
#Configuration
#ComponentScan("com.learn.service")
public class ServiceConfig {
public ServiceConfig() {
super();
}
}
the runner
#SpringBootApplication
#Import({
ContextConfig.class,
PersistenceJpaConfig.class,
ServiceConfig.class,
WebConfig.class,
SecurityConfig.class
})
public class WebservicesLearningApplication {
public static void main(String[] args) {
SpringApplication.run(WebservicesLearningApplication.class, args);
}
}
For the same configurations, the controller for User is working fine whose Service layer exists in the same package as that of Role.
package com.learn.controller;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET)
public List<User> findAll() {
System.out.println(userService);
List<User> users = userService.findAll();
return users;
}
Service layer
package com.learn.service;
#Service
#Transactional
public class UserService {
#Autowired
private UserJpaRepository userJpaRepository;
public List<User> findAll(){
return userJpaRepository.findAll();
}
}
Accessing the localhost:8080/api/users is successful but localhost:8080/api/roles gives NullPointerException
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.learn.controller.RoleController.findAll(RoleController.java:30) ~[classes/:na]............
Update1:
Web configuration class
#Configuration
#ComponentScan(basePackages = {"com.learn.controller"})
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
public WebConfig() {
super();
}
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
Optional<HttpMessageConverter<?>> convertFound = converters.stream().filter(c -> c instanceof AbstractJackson2HttpMessageConverter).findFirst();
if(convertFound.isPresent()) {
final AbstractJackson2HttpMessageConverter converter = (AbstractJackson2HttpMessageConverter) convertFound.get();
converter.getObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
converter.getObjectMapper().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}
}
screenshot of project structure
Update2 : I tried using the same UserService using #Autorired in a jUnit test case, and everything is working there. No nullpointer exception.
#ContextConfiguration(classes = {PersistenceJpaConfig.class, ContextConfig.class, ServiceConfig.class})
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class RoleTest {
#Autowired
private RoleService roleService ;
#Test
public void checkIfAllRolesCanBeRetrieved() {
List<Role> roles = roleService.findAll();
Assert.assertNotNull(roles);
}
}
This happened to me! in my case I had a controller using service,The service used a method of a class that did not have a #service,#controller or another annotation and I inject in service then when I use parent service error null occurred.
I hope that it will be used

Why #PostConstruct not invoked in spring container?

I tried to add some entities in the db shema
config:
#Configuration
#ComponentScan(ApplicationConfig.basePackage)
public class ApplicationConfig {
public final static String basePackage = "test"
}
spring container invocation:
public class StartApp {
public static void main(String... args) throws Exception{
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig.class);
TestEntityRepository repository = (TestEntityRepository) context.getBean("testEntityRepository");
repository.save(new TestEntity("test"));
}
}
target class with annotation:
public class PersistenceService {
#Autowired
TestEntityRepository testEntityRepository;
#PostConstruct
public void initialize(){
//repository.deleteAll();
testEntityRepository.save(new TestEntity("test1"));
testEntityRepository.save(new TestEntity("test2"));
testEntityRepository.save(new TestEntity("test3"));
}
}
as the result in table only one record - "test". At the Tomcat all works fine.
https://github.com/GlebSa/TestSpringJPA
It seems your PersistenceServiceis not recognized as a Service. Can you add the #Service to PersistenceService?
#Service
public class PersistenceService {
...
}
Hope this help.

How to use annotation and avoid xml configuration in spring framework

I have designed a packing structure.
Controller
Delegates (which is helper class) - this class do all the business and return the value to Controllers.
Service
Service Implementation
DAO
DAO Implementation.
I want to implement autowired (Annotation) concept and would like to avoid xml configuration such as service and DAO configuration on spring-bean.xml.
This code is not working if I want to avoid xml configuration.
I have done those changes
bean id :loginDelegate, userService, userDao
added the #Service & #Repository annotation to the corresponding service & DAO implementation.
#Controller("loginController")
public class LoginController {
#Autowired
private LoginDelegate loginDelegate;
public LoginDelegate getLoginDelegate() {
return this.loginDelegate;
}
public void setLoginDelegate(LoginDelegate tLoginDelegate) {
this.loginDelegate = tLoginDelegate;
}
#RequestMapping(value="/login.do",method=RequestMethod.GET)
public ModelAndView displayLogin(HttpServletRequest request, HttpServletResponse response) {
log.info("<---displayLogin()--->");
ModelAndView model = new ModelAndView("login");
LoginBean loginBean = new LoginBean();
model.addObject("loginBean", loginBean);
return model;
}
}
public class LoginDelegate {
#Autowired
private IUserService userService;
public IUserService getUserService() {
return this.userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public boolean isValidUser(String username, String password) throws Exception {
return userService.isValidUser(username, password);
}
}
public interface IUserService {
public boolean isValidUser(UserBean userObj);
public int addUsers(UserBean userObj);
}
public class UserServiceImpl implements IUserService {
#Autowired
private IUserDao userDao;
public IUserDao getUserDao() {
return this.userDao;
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
public boolean isValidUser(UserBean userObj) {
return userDao.isExistUser(userObj);
}
#Override
public int addUser(final UserBean userObj) {
return userDao.saveUserDetails(userObj);
}
}
public interface IUserDao {
public boolean isExistUser(UserBean userObj);
public int saveUserDetails(UserBean userObj);
}
public class UserDaoImpl implements IUserDao {
#Autowired
UserBean userObj;
#Autowired
DataSource dataSource ;
public DataSource getDataSource(){
return this.dataSource;
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
Use Java-based configuration if you want to completely get rid of XML-based configuration
#Configuration
#ComponentScan(basePackages = "com.acme")
public class AppConfig {
...
}
The above normal Java class when annotated with #Configuration, makes it a 'Spring Configuration class' (analogous to XML-based configuration).
#ComponentScan annotation scans for classes annotated with #Component, #Controller, #Service, #Repository classes from the package defined during start-up time to get them registered as Spring beans. This can be done in XML also with <context:component-scan base-package="com.acme" />
Refer:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-java-instantiating-container-scan

Resources