I have Controllers, Services and DAOs in separate spring boot modules. I tried calling a stored procedure from DAO module using JPA API StoredProcedureQuery method, for that I need to autowire EntityManager. This set up works if I run DAO alone as a spring boot application. But I am getting NullPointerException when I call this DAO class from controller.
My LoginDAO in DAO project
#Repository
public class LoginDAO implements ILoginDAO {
#Autowired
EntityManager entityManager;
#Transactional
public LoginEntity getLoginCheck(String[] loginfo) {
StoredProcedureQuery storedProcedure =entityManager.createStoredProcedureQuery("DPR_LOGIN_CHECK");
}
}
My LoginController class in Controller Module
#Controller
public class LoginController {
#Autowired
LoginDAO loginDAO;
#RequestMapping(value = "/LoginAction", method = RequestMethod.POST)
public #ResponseBody
String getLoginCheck(#RequestParam(value = "dataString") String dataString,
HttpSession session, HttpServletRequest request,
HttpServletResponse response) {
loginDAO.getLoginCheck(null,loginDetails);
}
}
My controller project is dependent on DAO. Here is my main controller class
#SpringBootApplication(scanBasePackages={"com.mars.presentation","com.mars.UserManagementControllers","com.mars","com.mars.CommonDAO"})
public class MarsApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MarsApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(MarsApplication.class, args);
}
}
and main DAO class
#SpringBootApplication(scanBasePackages={"com.mars.CommonDAO"})
#EntityScan(basePackages={"com.mars.CommonEntities"})
#EnableJpaRepositories
public class CommonDao {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(CommonDao.class, args);
String[] loginfo = new String[] {"cjva", "Banaacvdvna", "Orange", "Grapes"};
LoginDAO loginDAO = ctx.getBean(LoginDAO.class);
loginDAO.getLoginCheck(null,loginfo);
}
}
Related
I build a web project with spring boot 1.5.4
And create a class implements ApplicationContextAware
#Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.context = context;
}
public static ApplicationContext getContext() {
return context;
}
Then I create a controller to test this class
#Controller
public class TestController {
#RequestMapping(value = "test", method = RequestMethod.GET)
public #ResponseBody String test(){
System.out.println(SpringContextUtils.getContext());));
return "aaa";
}
}
than I start the application
#SpringBootApplication
#ServletComponentScan
#EnableTransactionManagement
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I visited this controller but SpringContextUtils.getContext() out put null,why?
I am sure SpringContextUtils scaned by spring.
I know I can use #Autowired to get ApplicationContext,but I want to know why my program is wrong and how can I get it with ApplicationContextAware
I have following repository which extends jpa repositroy and also have an implementation class where i have autowired this.
#Repository
public interface ProjectDAO extends CrudRepository<Project, Integer> {}
#Service
public class ProjectServiceImpl {
#Autowired private ProjectDAO pDAO;
public void save(Project p) { pDAO.save(p); } }
Now i have one Application.java class
Class Application{
public static void main(String..s){
// I need a way to call a method of repository
}
}
configuration file
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories
#PropertySource("file:/Users/abc/Documents/application.properties")
public class PersistenceContext {
#Autowired
Environment environment;
So how do we call this from main in case i dont to use any web based controller?
This is a way:
class Application {
public static void main(String[] s){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
ProjectDAO dao = applicationContext.getBean(ProjectDAO.class);
}
}
Edit:
class Application {
public static void main(String[] s){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
ProjectServiceImpl service = applicationContext.getBean(ProjectServiceImpl.class);
}
}
I'm doing unit test using spring mvc test framework.
The following is my source code:
com.exmple.main
MyController.java
#Controller
public class MyController {
#Autowired
private MyService myService;
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public Map<Object, Object> myControllerFunction(#RequestBody final Object jsonRequest) {
/* do something */
return response;
}
}
MyRepository.java
#Repository
public interface MyRepository extends JpaRepository<My, String> {
#Query(value="select * from my d where (d.start_date<to_date(:date,'YYYY/DD/MM')) and (d.end_date>to_date(:date,'YYYY/DD/MM'))", nativeQuery=true)
List<My> findByDate(#Param("date") String date);
}
MyService.java
public interface MyService {
List<My> findByDate(String date);
}
MyServiceImpl.java
#Service
public class MyServiceImpl implements MyService {
#Autowired
MyRepository destRepo;
#Override
public List<My> findByDate(String date) {
List<My> listDest = destRepo.findByDate(date);
return listDest;
}
}
com.example.test
MyControllerTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={TestConfig.class})
#WebAppConfiguration
public class MyControllerTest {
private MockMvc mockMvc;
#Autowired
MyService myService;
#Autowired
protected WebApplicationContext webApplicationContext;
#Before
public void setup() throws Exception {
// this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void listAllMy() throws Exception {
}
}
TestConfig.java
#Configuration
public class TestConfig {
#Bean
public MyService myService() {
// set properties, etc.
return new MyServiceImpl();
}
}
When I run test, the following error is displayed
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
I know the exception occurred because MyService didn't find any bean of MyRepository.
But I don't know how to create a bean of repository.
Please teach me how to create a bean of repository class using Java (not xml).
You need to enable the JPA repositories in your config class, specify the package that contains the repositories as below
#Configuration
#EnableJpaRepositories(basePackages = {
"com.example.repository"
})
public class TestConfig {
#Bean
public MyService myService() {
// set properties, etc.
return new DestinationServiceImpl();
}
}
Edit: looks like you haven't defined entityManager, and dataSource. Refer to a tutorial here and also answer to similar question here
I'm a newbie to Spring. I'm facing a problem with Spring-Boot. I'm trying to autowire a field from an external config file into an autowired bean. I have the following classes
App.java
public class App {
#Autowired
private Service service;
public static void main(String[] args) {
final SpringApplication app = new SpringApplication(App.class);
//app.setShowBanner(false);
app.run();
}
#PostConstruct
public void foo() {
System.out.println("Instantiated service name = " + service.serviceName);
}
}
AppConfig.java
#Configuration
#ConfigurationProperties
public class AppConfig {
#Bean
public Service service() {
return new Service1();
}
}
Service Interface
public interface Service {
public String serviceName ="";
public void getHistory(int days , Location location );
public void getForecast(int days , Location location );
}
Service1
#Configurable
#ConfigurationProperties
public class Service1 implements Service {
#Autowired
#Value("${serviceName}")
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.
public void getHistory(int days , Location location)
{
//history code
}
public void getForecast(int days , Location location )
{
//forecast code
}
}
I'm unable to display the service name variable in the postconstruct method of the App class. Am I doing this right?
You can load properties in different ways:
Imagine the following application.properties which is automatically loaded by spring-boot.
spring.app.serviceName=Boot demo
spring.app.version=1.0.0
Inject values using #Value
#Service
public class ServiceImpl implements Service {
#Value("${spring.app.serviceName}")
public String serviceName;
}
Inject values using #ConfigurationProperties
#ConfigurationProperties(prefix="spring.app")
public class ApplicationProperties {
private String serviceName;
private String version;
//setters and getters
}
You can access to this properties from another class using #Autowired
#Service
public class ServiceImpl implements Service {
#Autowired
public ApplicationProperties applicationProperties;
}
As you can notice the prefix will be spring.app then spring-boot will match the properties prefix with that and look for serviceName and version and values will be injected.
Considering you have you class App annotated with #SpringBootApplication and App class in the top package You can put your serviceName inside application.properties and inject it using #Value("${serviceName}"). Do not use #Component on a class if you are already using #Bean on configuration it will clash, and so #Autowired with #Value
See docs for more info
You will end with something like
#Service // #Component specialization
public class Service1 implements Service {
#Value("${serviceName}")
public String serviceName;
//Available in external configuration file.
//This autowiring is not reflected in the main method of the application.
public void getHistory(int days , Location location)
{
//history code
}
public void getForecast(int days , Location location )
{
//forecast code
}
}
No need for #Bean declaration when you have #Component/#Service/#Repository
#Configuration
public class AppConfig { //other stuff here not duplicated beans }
And your main class
package com.app;
#SpringBootApplication // contains #EnableAutoConfiguration #ComponentScan #Configuration
public class App {
#Autowired
private Service service;
public static void main(String[] args) {
final SpringApplication app = new SpringApplication(App.class);
//app.setShowBanner(false);
app.run();
}
#PostConstruct
public void foo() {
System.out.println("Instantiated service name = " + service.serviceName);
}
}
Dao
#Repository
public interface LoginDao extends JpaRepository<Login, Integer> {
Login findByLogin(String login);
}
Validator
#Component
public class PasswordChangeValidator implements Validator {
private LoginDao loginDao;
#Override
public boolean supports(Class<?> aClass) {
return PasswordChange.class.equals(aClass);
}
#Override
public void validate(Object o, Errors errors) {
PasswordChange passwordChange = (PasswordChange) o;
**// There is a null pointer here because loginDao is null**
Login login = loginDao.findByLogin(passwordChange.getLoginKey());
}
public LoginDao getLoginDao() {
return loginDao;
}
#Autowired
public void setLoginDao(LoginDao loginDao) {
**// There is a debug point on the next line and it's hit on server startup and I can
// see the parameter us non-null**
this.loginDao = loginDao;
}
}
Controller
#Controller
#RequestMapping("api")
public class PasswordController {
#Autowired
PasswordService passwordService;
#InitBinder("passwordChange")
public void initBinder(WebDataBinder webDataBinder, WebRequest webRequest) {
webDataBinder.setValidator(new PasswordChangeValidator());
}
#RequestMapping(value = "/passwordChange", method = RequestMethod.POST)
public #ResponseBody PasswordInfo passwordInfo(#RequestBody #Valid PasswordChange passwordChange)
throws PasswordChangeException {
return passwordService.changePassword(passwordChange.getLoginKey(), passwordChange.getOldPassword(), passwordChange.getNewPassword());
}
}
I have the Dao listed above. This same dao bean gets injected in an #Service annotated class but not in #Component annotated Validator class. Well, not exactly the upon server startup I can see that the setter method gets called, but when I try to use this variable in a method the variable shows as null.
Does anybody see a problem with my configuration ? Please note that the loginDao bean gets injected into a service class, so the Context configuration is good.
Well there's your problem
webDataBinder.setValidator(new PasswordChangeValidator());
Spring can only manage beans it created. Here, you're creating the instance. Instead inject your bean into the #Controller and use it.
#Inject
private PasswordChangeValidator passwordChangeValidator;
...
webDataBinder.setValidator(passwordChangeValidator);