Spring boot controller not being detected - spring-boot

Good day. I'm having issues with my Springboot app. The controller isn't being detected.The Component scan is used but it won't detect the controllers.
Folder structure
Application
#EntityScan(basePackages = "com.jokedata.models")
#EnableJpaRepositories(basePackages = "com.jokedata.repositories")
//#ComponentScan(basePackages = {"com.jokeweb.project.controllers"})
#SpringBootApplication(scanBasePackages = "com.jokeweb.project.controllers")
public class JokeApplication {
public static void main(String[] args) {
SpringApplication.run(JokeDataApplication.class, args);
}
}
Controller
#RestController
public class UserController {
#GetMapping("/home")
public String home() {
return "home";
}
}

Check if request URL or application port is correct or not.

Related

Spring Boot #Component doesn't create Beans

Since according to the docs #Component registers beans for the Spring container I'm trying to create a simple example of dependency injection using the following code:
package pl.playground;
//...
#SpringBootApplication
public class PlaygroundApplication {
#Autowired
private static Building building;
public static void main(String[] args) {
building.setBuildingSize(12L);
System.out.println(building.monthlyHeatingCost());
}
}
package pl.playground.facade;
//...
#Component
public class Building {
private HeatingService service;
private Long buildingSize;
#Autowired
public Building(HeatingService service) {
this.service = service;
}
public Double monthlyHeatingCost() {
return service.getMonthlyHeatingCost(buildingSize);
}
// getters & setters...
}
package pl.playground.service;
public interface HeatingService {
Double getMonthlyHeatingCost(Long size);
}
package pl.playground.service;
//...
#Component
public class HeatingServiceImpl implements HeatingService {
private final Double CUBIC_PRICE = 2.3;
public HeatingServiceImpl() {}
#Override
public Double getMonthlyHeatingCost(Long size) {
return size * CUBIC_PRICE;
}
}
It builds and runs, but there is a NullPointerException at building.setBuildingSize(12L);. However the one below works without any issues:
//PlaygroundApplication.java
package pl.playground;
//...
#SpringBootApplication
public class PlaygroundApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Building building = context.getBean(Building.class);
building.setBuildingSize(12L);
System.out.println(building.monthlyHeatingCost());
}
}
package pl.playground.config;
//...
#Configuration
public class Config {
#Bean
public Building building(HeatingService service) {
return new Building(service);
}
#Bean
public HeatingServiceImpl heatingServiceImpl() {
return new HeatingServiceImpl();
}
}
The rest is the same as before.
Why is #Component not creating Beans?
It is working the way I think it should when used inside a #Controller of a web app, does that make a difference? How does exactly #Bean and #Component differ?
What am I failing to understand?
EDIT
Consider the following scenario:
package pl.playground;
//...
#SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
package pl.playground.controller;
//...
#Controller
public class Controller {
private Facade facade;
#Autowired
public Controller(Facade facade) {
this.facade = facade;
}
#GetMapping("/")
public String getIndexPage(Model model) {
return "index";
}
}
package pl.playground.facade;
//...
#Component
public class Facade {
private PostsService postService;
private UserService userService;
private TagService tagService;
#Autowired
public Facade(PostsService retrieve, UserService user, TagService tag) {
this.postService = retrieve;
this.userService = user;
this.tagService = tag;
}
//...
}
I don't need #Configuration here for it to work. That's my concern.
The problem with your code is that you are trying to #Autowire on a static field. You simply cannot do that. Look here: Can you use #Autowired with static fields?
It fails to work because the PlaygroundApplication class is not being created and managed by spring. The injection works only inside instances managed by spring. You can treat class annotated with #SpringBootApplication as configuration classes. Spring creates instances of those classes and injection works inside them but only on instance fields.
The second example shows the correct way to access spring beans from main method of the application.
Well. I used your original question and is working without any issues. #cezary-butler pointed out in the comments you can autowire into PlaygroundApplication but you can get hold of it easily in the static main method using context.getBean(Building.class)
#SpringBootApplication
public class PlaygroundApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
SpringApplication.run(PlaygroundApplication.class);
Building building = context.getBean(Building.class);
building.setBuildingSize(12L);
System.out.println(building.monthlyHeatingCost());
}
}
Here is the sample repo https://github.com/kavi-kanap/stackoverflow-63072236
TLDR;
A Spring context needs to be created before any bean can be injected. In the first scenario, just the fact of having a #SpringBootApplication decorator does not ensure a context in the scope of the class it decorates.
SpringApplication.run(ExampleApplication.class, args); instantiates a context (and e.g. a web server among other things)
var context = new AnnotationConfigApplicationContext(Config.class); instantiates a scoped context
Thus the first example had null inside of Building as there was no context with the bean to inject.

Swagger UI does not show Params

I've got a Spring-Application (2.1.0.RELEASE) and added Swagger and Swagger-UI (2.9.2).
I have a SwaggerConfig class, that I copied from the Baeldung tutorial
Then, there is the App class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#EnableAutoConfiguration
public class App
{
public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
}
And there is the actual REST controller:
#RestController
public class TweetRating {
#GetMapping("/{userid}/tweet")
public static void getTweet(#PathVariable String userid){
System.out.println("UserID: "+ userid);
}
#GetMapping("/")
public static void isWorking(#RequestParam String id){
System.out.println("ID: "+ id);
}
}
The Swagger-UI just won't show the params of the methods. Neither the PathVariable not the RequestParam. Therefore, the "Try it out" function does not make any sense, of course. It looks like this:
Screenshot1
Screenshot2
Why is that and how can I solve it?
Try to apply enableUrlTemplating(true) in you SwaggerConfig :
#Configuration
#EnableSwagger2
public class SwaggerConfig {                                   
    #Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2) 
          .select()                                 
          .apis(RequestHandlerSelectors.any())             
          .paths(PathSelectors.any())  
.enableUrlTemplating(true)                       
          .build();                                          
    }
Also try this one :
#ApiOperation(value = "Dexcription of endpoint")
#RequestMapping
public String doSomething(#ApiParam(value = "Description of path vaiable")#PathVariable("/{code}")

Spring Boot and GlassFish

I actually have a spring boot application that i deployed on glassfish server 5.0 .
The probleme is that the jsp pages are not showing when i type the link.
I correctly configured the main class:
#SpringBootApplication
public class CaisseApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(CaisseApplication.class, args);
}
}
the controller looks like this:
#Controller
#RequestMapping("/imports_caisses_et_grandsLivres/")public class controller {
#RequestMapping(value = "")
public String index(Map<Object, Object> model) {
return "index";
}
}
The jsp pages are correctly created, and to acces them, i'm using application.properties:
spring.mvc.view.prefix= /WEB-INF/views/
spring.mvc.view.suffix= .jsp
Sorry, the brackets {} was missing in:
#Controller
#RequestMapping({"/imports_caisses_et_grandsLivres/"})

#RestController returning blank

I'm building my first Spring Boot application. But I can't get my requestMapping controller answer properly.
This is my main class:
package com.hello.world;
#SpringBootApplication
public class HelloWorld implements CommandLineRunner{
public static void main(String[] args) {
SpringApplication.run(HelloWorld.class, args);
}
#Override
public void run(String... args) throws Exception {
....
}
}
And this is my RestController:
package com.hello.world.controllers;
#RestController
public class UrlMappingControllers {
#RequestMapping("/hi")
String home() {
return "Hello World!";
}
}
If I take a look at the log I can see the "/hi" mapping:
restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/hi]}" onto java.lang.String com.hello.world.controllers.UrlMappingControllers.home()
But when I access: http:localhost:8080/hi I get a blank page, I expected seing the "Hello World" text.
Why am I getting a blank page?
--- Edit ----
I've just realised that I am getting the blank page only when I add a cxf service. I think it is because the #configuration annotation on this class:
package com.hello.world.helloWorld.configuration;
#Configuration
public class CXFConfiguration {
#Bean
public ServletRegistrationBean dispatcherServlet() {
return new ServletRegistrationBean(new CXFServlet(), "/services/*");
}
#Bean(name=Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
SpringBus springBus = new SpringBus();
return springBus;
}
#Bean
public Endpoint endpointGreentingService() {
EndpointImpl endpoint = new EndpointImpl(springBus(), new GreetingServiceImpl());
endpoint.getFeatures().add(new LoggingFeature());
endpoint.publish("/GreetingService");
return endpoint;
}
}
Could it be related?
#RestController = #Controller + #ResponseBody which means that when you call your api at http:localhost:8080/hi the body of the response will contain the result of the home() handler, i-e "Hello world".
#RestControllerbehind the scene makes Spring MVC uses a Json Message Converter (by default) and all handler methods inside a class annoted with #RestController will return a JSON, that is why you do not see your text on your browser.
You can use Postman or ARC to test your app. Some web browsers like Firefox shows JSON directly.

access to property in external file works in controller but not in domain class

I have a property set in an external application.properties file and find that I can access it in the controller but not in the domain class. I'm using SpringBoot 1.1.9 and groovy and code snippets listed below.
Can someone please explain what I'm missing here?
Thanks!
--john
//Application class used to startup
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
//Controller - property is injected
#RestController
class CityController {
#Value( '${sample.property}' )
String stringTemplate
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(HttpServletResponse response) {
return String.format(stringTemplate, 'world')
}
}
//Domain class - property does not seem to be injected
#Component
public class City {
#Value( '${sample.property}' )
String stringTemplate
String toString() {
return String.format(stringTemplate, 'world')
}
}

Resources