Let's say we got two different controller classes, AController.java and BController.java.
public class AController {
#Autowired
private AdminService adminService;
}
public class BController {
#Autowired
private AdminService adminService;
}
I wonder if this is okay.
+ EDIT
AdminService (Interface)
The top three are from Acontroller, and the other is from BController.
I have no issue with trigger selectNormalList() until I create selectCouponByTerm().
public interface AdminService {
List<Member> selectNormalList();
List<Member> selectPartnerList();
List<Coupon> selectCouponByDate(String date);
List<Coupon> selectCouponByTerm(String startDate, String endDate);
}
AdminServiceImpl(that implements interface AdminService)
#Service
public class AdminServiceImpl implements AdminService{
#Autowired
private static AdminDao adminDao;
#Override
public List<Member> selectNormalList() {
return adminDao.selectNormalList();
}
#Override
public List<Member> selectPartnerList() {
return adminDao.selectPartnerList();
}
#Override
public List<Coupon> selectCouponByDate(String date) {
return adminDao.selectCouponByDate(date);
}
#Override
public List<Coupon> selectCouponByTerm(String startDate, String endDate) {
return adminDao.selectCouponByTerm(startDate, endDate);
}
}
I suggest the following approach for the Service class
The way you are structured the logic will lead you to NULLPointerException
#Service
public class AdminServiceImpl implements AdminService{
private AdminDao adminDao;
#Autowired
private AdminService adminService;
public AdminServiceImpl (AdminDao adminDao){
this.adminDao= adminDao;
#Override
public List<Member> selectNormalList() {
return adminDao.selectNormalList();
}
#Override
public List<Member> selectPartnerList() {
return adminDao.selectPartnerList();
}
#Override
public List<Coupon> selectCouponByDate(String date) {
return adminDao.selectCouponByDate(date);
}
#Override
public List<Coupon> selectCouponByTerm(String startDate, String endDate) {
return adminDao.selectCouponByTerm(startDate, endDate);
}
Then in your controllers
#Controller
public class AController {
#Autowired
private AdminService adminService;
}
#Controller
public class BController {
#Autowired
private AdminService adminService;
}
Yes.
This is the point of dependency injection. You can inject a dependency into whatever else needs it.
Do pay attention to what you're injecting where, though; if two controllers share common functionality to the degree that they have the same dependencies, should they really be two controllers?
Yes. It is ok. Spring will inject AdminService in both controllers. You have to use #Controller on AController and BController and #Service on AdminService class.
Related
I get null logservice in after method.
I used #Component, #ComponentScan, #Service and #Configuration, but none worked.
Here is my Listener class
#Component
public class LogOrder {
private static LogService logService;
#Autowired
public void setLogService(LogService logService) {
LogOrder.logService = logService;
}
#PostUpdate
private void after(Order order) {
logService.log("Logged");
}
}
Here is my Entity class
#EntityListeners(LogOrder.class)
#Entity
public class Order{
}
Here is LogService interface and its implementation
public interface LogService {
void send("");
}
#Service(value = "logService")
public class LogServiceImpl implements LogService {
private final SomeOtherService someOtherService;
#Autowired
public LogServiceImpl(SomeOtherService someOtherService) {
this.someOtherService = someOtherService;
}
public void send(String someText) {
SomeTemplate someTemplate = someOtherService.someTemplate();
someTemplate.convertAndSend(someText);
}
}
What can I do to get LogService not null.
You are trying to autowire a static field.
private static LogService logService;
Remove static from the attribute.
I have a Java Spring boot project that I'm creating a post request in. The code looks like this:
Main:
#SpringBootApplication
public class Main
{
public static void main(String[] args)
{
SpringApplication.run(Main.class,args);
}
}
Java bean:
#Data
#Entity
public class Image {
private #Id #GeneratedValue Long id;
private String imageNo;
private String name;
private Image(){}
public Image(String imageNo, String name){
this.imageNo = imageNo;
this.name = name;
}
}
Repository:
public interface ImageRepository extends CrudRepository<Image, Long> {
}
DatabaseLoader:
#Component
public class DatabaseLoader implements CommandLineRunner {
private final ImageRepository repository;
#Autowired
public DatabaseLoader(ImageRepository repository) {
this.repository = repository;
}
#Override
public void run(String... strings) throws Exception {
this.repository.save(new Image("1", "Baggins"));
}
}
However when I run the project I get the following error:
Description:
Parameter 0 of constructor in com.face.DatabaseLoader required a bean of type 'com.face.ImageRepository' that could not be found.
Action:
Consider defining a bean of type 'com.face.ImageRepository' in your configuration.
Grateful for any help with this!
Many thanks,
Your spring container will not scan Image repository, since it's not annotated. To fix this you should annotate the ImageRepository with #Repository annotation as below -
#Repository
public interface ImageRepository extends CrudRepository<Image, Long> {
}
I'm trying to write a really basic application using Spring-Boot. The only thing I'm currently trying is to get some information out of a SQL Server database.
Application.java
#SpringBootApplication(scanBasePackageClasses = { MainView.class, Application.class })
#EnableJpaRepositories(basePackageClasses = CustomerRepository.class)
#EntityScan(basePackageClasses = Customer.class)
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
Customerrepository.java
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer>
{
}
CustomerController.java
#Controller
#RequestMapping(path = "/customer")
public class CustomerController {
#Autowired
private CustomerRepository customerRepository;
#GetMapping(path = "/all")
public #ResponseBody Iterable<Customer> getAllCustomers() {
return customerRepository.findAll();
}
}
CustomersView.java
#Tag("customers-view")
#HtmlImport("src/views/customers/customers-view.html")
#Route(value = ApplicationConst.PAGE_CUSTOMERS, layout = MainView.class)
#PageTitle(ApplicationConst.TITLE_CUSTOMERS)
public class CustomersView extends PolymerTemplate<TemplateModel> {
#Autowired
CustomerRepository customerRepository;
public CustomersView() {
customerRepository.findAll();
}
}
Going to http://localhost:8080/customer returns every customer in my database just fine.
But when I try to find all the customers in my CustomersView.java, the autowired CustomerRepository returns a nullpointerexception.
Is somebody able to point me in the right direction?
Try to #Autowire the Repository in the constructor like this:
#Tag("customers-view")
#HtmlImport("src/views/customers/customers-view.html")
#Route(value = ApplicationConst.PAGE_CUSTOMERS, layout = MainView.class)
#PageTitle(ApplicationConst.TITLE_CUSTOMERS)
public class CustomersView extends PolymerTemplate<TemplateModel> {
CustomerRepository customerRepository;
#Autowired
public CustomersView(CustomerRepository customerRepository) {
this.costumerRepository = customerRepository;
this.customerRepository.findAll();
}
}
This happens because all #autowired-attributes are inserted after the constructor gets completed. If you want to inject the #autowired-attributes at constructor-time, you have to use the method above.
I want to call all the request mapping method(which has #Resource injection) before the server starts. How I can do this?
#Controller
public class ServiceController {
#Resource(name="userService")
private IUserService userService;
#RequestMapping("/getAllCountry")
public String getAllCountry() {
return userService.getAllCountry();
}
#RequestMapping("/getAllStates")
public String getAllStates() {
return userService.getStates();
}
#PostConstruct
public void cacheData(){
cache.put("ALL_COUNTRY_DATA", getAllCountry());
cache.put("ALL_STATE_DATA", getAllStates());
}
}
The above code fails and give me IllegalStateException. What is the best way to call the request mapping methods before the server is up and populate the cache.
Try using ApplicationListener in conjunction with ContextRefreshedEvent:
#Controller
public class ServiceController implements ApplicationListener<ContextRefreshedEvent> {
private static final Map<String, String> cache = new HashMap<>();
#Resource(name = "userService")
private IUserService userService;
#RequestMapping("/getAllCountry")
public String getAllCountry() {
return userService.getAllCountry();
}
#RequestMapping("/getAllStates")
public String getAllStates() {
return userService.getStates();
}
public void cacheData() {
cache.put("ALL_COUNTRY_DATA", getAllCountry());
cache.put("ALL_STATE_DATA", getAllStates());
}
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
cacheData();
}
}
I'm trying to create a simple web-page, which is displaying the data, received from web-service
#Service
#Transactional
public class TopicService {
#Autowired
private TopicRepository topicRepository;
public int saveTopic(Topic topic){
return topicRepository.save(topic).getId();
}
public Iterable<Topic> findAllTopics(){
return topicRepository.findAll();
}
public Topic findTopicByID(Long id){
return topicRepository.findOne(id);
}
public List<Topic> findTopicsByTag(Tag tag){
return topicRepository.findAllByTopicTag(tag);
}
}
topic repository extends CRUD-repository
#Repository
public interface TopicRepository extends CrudRepository<Topic, Long>
{
List<Topic> findAllByTopicTag(Tag currentTag);
}
the controller invokes a service in the following way
#Controller
public class HomeController {
private TopicService service;
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model)
{
Iterable<Topic> listTopic = service.findAllTopics();
return new ModelAndView("home", "model", listTopic);
}
}
this string
Iterable listTopic = service.findAllTopics();
throws null-pointer exception. I guess, because the service isn't initialized. How could I perform correct initialization of the service?
You need to autowire the TopicService in HomeController:
#Controller
public class HomeController {
#Aurowired
private TopicService service;