Spring Boot not finding RestController - java

So I've got a simple spring boot app, #SpringBootApplication, a stub #Configuration and a #RestController all in the same package. Spring-boot-web-starter is there and the webserver comes up fine, actuator endpoints and all. But I cannot for the life of me get the app to pick up the #RestControllers.
enter image description here
Main.class:
package com.iglossolalia.munin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(MuninContext.class, args);
}
}
MuninContext.class:
package com.iglossolalia.munin;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
public class MuninContext {
}
MuninService.class:
package com.iglossolalia.munin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MuninService {
private static final Logger LOG = LoggerFactory.getLogger(MuninService.class);
public MuninService() {
LOG.info("Started MuninService");
}
#GetMapping("/health")
public String healthCheck() {
return "pong";
}
}
Tried explicitly adding the rest controller to the component scan with no luck there.

You have no #ComponentScan annotation in your MuninContext. Actually you can write SpringApplication.run(Main.class, args) in main method as Spring Initializr generate by default, you don't really need your context, because #SpringBootApplication work as configuration and contains #EnableAutoConfiguration, #ComponentScan, and some other annotations. Otherwise, as you pass your config class as argument in SpringApplication.run method, annotation #SpringBootApplication in Main class has no effect

Related

Spring Boot #Autowired object - Nullpointer Exception [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 3 years ago.
I am developing a spring boot application to send sms notification. This is my class for the purpose.
package org.otp.services;
import org.otp.Configurations;
import com.mashape.unirest.http.HttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
#Component
public class SmsService
{
private static final Logger LOG = LoggerFactory.getLogger(SmsService.class);
public String send(String mobile, String msg)
{
//Code
}
}
And this is the class which uses the above class for sending notification.
package org.otp.controllers;
import org.otp.Constants;
import org.otp.services.EmailService;
import org.otp.services.SmsService;
import org.otp.dto.MessageRequest;
import org.otp.dto.MessageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
#Component
public class MessageController {
private static final Logger LOG = LoggerFactory.getLogger(MessageController.class);
#Autowired
SmsService smsService;
public void sendMessageToAlert(#RequestBody MessageRequest messageRequest)
{
String smsStatus = "FAIL";
MessageResponse messageResponse = new MessageResponse();
//1. Nullpointer
smsStatus = smsService.send(messageRequest.getMobileNo(),messageRequest.getMessage());
}
}
Main Class
package org.otp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class OtpServiceApplication implements ApplicationRunner
{
public static void main(String[] args) {
SpringApplication.run(OtpServiceApplication.class, args);
}
}
Problem is, I get a nullpointer exception in the (1) stating that my SmsService object is null. And my main class is in package org.otp so the two classes here falls under sub package so no need of component scan.
Therefore I am confused what to do to solve this. I have tried many answers here like adding a #Component annotation and #ComponentScan in main class but nothing works. Could someone please point out my mistake here.
Thanks in advance.
If your #Autowired annotation is not working and throws NPE ,it means that spring fails to create an instance of the component class in the application context . Try to:
Verify that the classes are in class path for scanning and also check to ensure that all auto-wired classes have the annotation #Component to enable them to be picked up during class path scanning.
Check the spring boot start up logs to verify if there are any errors
during bean creation.
Check to ensure all related classes used in the service layer are auto-wired properly and that the injected classes are annotated with #Component .
For further help please share the main application class along with your project structure.
Since you are using springboot , it is preferable to use the sprinboot stereotype annotations instead of the #Component annotation, if you are building a standard springboot web application.
#Service : for the service layer.
#Controller : for the controller layer . Also,DispatcherServlet will look for #RequestMapping on classes which are annotated using #Controller but not with #Component.
In Springboot application's main class add following annotation
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}
While using annotations we should configured with #ComponentScan annotation to tell Spring the packages to scan for annotated components. This should be used in mail class(Which class wants to load first) in your case you are working with spring boot so you should use this annotation in Springboot application's main class. Like below
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}

How to resolve the problem related to "Whitelabel Error Page" in a Spring Boot application

I am trying to execute my new Spring Boot application.
The first two classes are:
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class UbbioneApplication {
public static void main(String[] args) {
SpringApplication.run(UbbioneApplication.class, args);
}
}
then the servlet Initializer class
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(UbbioneApplication.class);
}
}
But when I am used to run my application by writing mvn spring-boot:run in the console, I have this message appearing:
Whitelabel Error Page
Could you help me please how to resolve this issue?
Thanks in advance.
I think I have an answer:
I created a controller to my application and I updated my code as following:
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = {"Name_controller_path"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Then my controller will look like this:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class Appcontroller {
#RequestMapping(value = "/home", method = RequestMethod.GET)
String home() {
return "home";
}
}
Then use this path to view your execution: http://localhost:8080/home.

Spring Boot YAML Config w/ unique file name

I am trying to read in a simple yml file for a Spring Boot application located at resources/wtf.yml. The following application works if the default application.yml filename is used, but not if I change the filename. Anyone know why this doesn't work?
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import javax.annotation.PostConstruct;
#EnableConfigurationProperties
#SpringBootApplication
#ConfigurationProperties(locations = {"wtf.yml"}) //classpath:wtf.yml
public class SomeApp {
public static void main(final String[] args) {
SpringApplication.run(SomeApp.class, args);
}
#PostConstruct
public void init() {
System.out.println(readTimeout);
}
#Value("${readTimeout}")
public int readTimeout;
}
You can use spring.config.name or spring.config.location properties as described in Spring Boot guide.

Usage of #Componenscan in Springboot Spring MVC Application

my problem is that i dont know how to specify the path for my Controller package to search for requestmapping annotations inside it in the #componenscan annotation, which is in the main class.
Project structure:
My DemoApplication class:
package com.personalitymeet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Configuration
#EnableAutoConfiguration
#ComponentScan()
#Controller
public class DemoApplication {
#ResponseBody
#RequestMapping("/")
String entry(){
return "bla";
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Usercontroller.java:
package com.personalitymeet.web;
import com.personalitymeet.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by mv on 15.09.2016.
*/
#Controller
public class UserController {
#RequestMapping("/user")
public String user(Model model){
User user = new User();
user.setFirstname("Misi");
user.setLastname("Varga");
model.addAttribute("user",user);
return "userview";
}
}
So, my question is, how can i tell springboots that it should search for #Requestmapping annotation in the Usercontroller class?
You can specify component scan to your configuration file to scan folder com.personalitymeet and it will automatically pick all the classes which has relevant annotations.
Below are basic 3 annotations needed to init application.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.personalitymeet")
Your problem isn't the #ComponentScan, which will search in com.personalitymeet and all subpackages. It's that for some reason you don't have the MVC infrastructure activating.
You should have spring-boot-starter-web as a dependency in your build.gradle file, and you should add #EnableWebMvc to your configuration class.
Can you replace this code:
#Configuration
#EnableAutoConfiguration
#ComponentScan()
#Controller
public class DemoApplication {
...
With this code:
#SpringBootApplication
#Controller
public class DemoApplication {
...
Configure your application to expose the management endpoints:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready
and then hit this endpoint to see the endpoint exposed by the application:
http://localhost:[port]/manage/mappings
Also, I recommend to create a separate controller for the root to keep your startup class uncluttered with application logic.

Issue with #Value and application.properties since moving to Spring Boot 1.1.4.RELEASE

I am having an issue since I moved to version 1.1.4.RELEASE of Spring Boot.
My variables that are annotated with #Value are presently not being populated with values despite them being present in the application.properties. Prior to this I was using Spring Boot # version 1.0.2, and that was working fine.
It all started since the upgrade, and I made no code change.
SampleApplication.java
package org.sample;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#ComponentScan
#EnableAutoConfiguration
#PropertySource(value = "classpath:application.properties")
public class SampleApplication {
private static Logger logger = LoggerFactory
.getLogger(TaskManagerApplication.class);
#Value("${org.sample.sampleProperty}")
private static String sampleProperty;
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
System.out.print("SampleApplication started: " + sampleProperty);
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
application.properties
spring.datasource.url: jdbc:mysql://127.0.0.1:3306/mydb
spring.datasource.username: root
spring.datasource.password: root
spring.datasource.driverClassName: com.mysql.jdbc.Driver
spring.jpa.show-sql: true
#Disable the ddl-auto:create once tables have been created
#spring.jpa.hibernate.ddl-auto: create
org.sample.sampleProperty=This is a sample property
photos.upload.dir=C:/temp/UserPhotos/
# Server port
server.port=8081
I have tried to add a PropertySourcesPlaceholderConfigurer bean and even PropertySourcesPlaceholderConfigurer but still the issue persists.
Anyone experienced this ? Or is there a new way to load the properties file ?
Please note that my db connection and server port are being read properly since my application can connect to db and I have to access it through the specified port.
sampleProperty variable remains null though.
#Value is not meant to work on static fields
Properties from application.properties are available automatically without specifying #PropertySource for it.
Instead of printing out property in main() method, you should do it after bean is constructed, for example by using #PostConstruct
Fully working example:
package demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
#Value("${org.sample.sampleProperty}")
private String sampleProperty;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#PostConstruct
public void postConstruct() {
System.out.print("SampleApplication started: " + sampleProperty);
}
}

Categories