How to run specific SpringBoot CommandLineRunner runner in my app? - spring-mvc

I'm following the Spring Boot CommandLineRunner : filter option argument for creating CommandLineRunner for my SpringBoot application. What I dont understand is how can I run this specific command in ma app? In this specific example there is a FileProcessingCommandLine class with 'run' method implemented. Now how can I run this from command prompt?

a think that cannot be run manually. Spring framework is responsible for running this method!.
You should mark your class with Spring’s #Component annotation so that will automatically picked up by #SpringBootApplication.
If your class implements Spring Boot’s CommandLineRunner it will run after all the beans are created and registered.
#Component
public class FirstCommandLineRunner implements CommandLineRunner {
#Override
public void run(String... strings) throws Exception {
System.out.println("hello world");
}
}

Related

Please help to explain a strange combination of Lombok's #AllArgsConstructor and spring's #RestController

I'm working on a spring project from our customer.
Below is the code for controller
#Log4j2
#RestController
#AllArgsConstructor
#RequestMapping(path = "/api/theapi")
#Api(value = "Description for the API")
public class TheAPIController {
private final ModelMapper modelMapper;
private final ObjectMapper objectMapper;
private final TheDemoService demoService;
...other code for controller
}
Below is the code for Service:
#Service
public class TheDemoService{ ... }
I was so surprise about 2 things:
Question 1: Why we need to use #AllArgsConstructor from project Lombok?
As per my understanding, Spring provide #RestController that Spring runtime container will initialize an Instance for our Controller. So that, having a constructor for our Controller seems like an invalid approach for using Spring Inversion of Control, is this correct?
Question 2. Because of using #AllArgsConstructor, somehow, the instance for demoService is to be injected
But again, I surprise because the code of Controller does not have #Autowired in combine with demoService.
In the actual code, there is no #Autowired for "private final TheDemoService demoService".
Hence, I could think of a possibility there, is that because of Lombok's #AllArgsConstructor would inject an instance of our TheDemoService via a constructor of
TheAPIController, I could not reason anything about this logic.
It's Invalid approach, no need for defining constructor for RestController
It's implicitly auto wiring the service
if a class, which is configured as a Spring bean, has only one constructor, the Autowired annotation can be omitted and Spring will use that constructor and inject all necessary dependencies.
To sum up #AllArgsConstructor can/should be removed

Avoid proliferation of #MockBeans in Spring Boot #WebMvcTest test

I have a simple controller e.g.
#Controller
public class FooController
{
#Autowired
private BarService barService;
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public String displayFoo()
{
return "foo";
}
}
When I want to do a #WebMvcTest, I have to create a great number of #MockBeans to prevent a NoSuchBeanDefinitionException.
#RunWith(SpringRunner.class)
#WebMvcTest
#Import(WebSecurityConfig.class)
public class FooControllerTest
{
#MockBean ...
#MockBean ...
#MockBean ...
...
...
}
Does this mean that BarService is somehow creating a chain of dependencies? (it has some dependencies but some #MockBeans appear completely unrelated).
The problem is, is that each #WebMvcTest I add for different controllers also requires the same #MockBeans.
Should I be using an annotation like #TestConfiguration to specify all the #MockBeans for the DRY principal?
I looked at this again, and found you can pass the controller name to #WebMvcTest e.g. #WebMvcTest(FooController.class).
Specifies the controllers to test. May be left blank if all {#code
#Controller} beans should be added to the application context.
As Hal8k said, if you don't specify a controller like #WebMvcTest(YourController.class), it will try to load all #Controller components. And #Import(WebSecurityConfig.class) also try to inject components in WebSecurityConfig.class.
Refer : https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4
This could happen when the bean scanning configuration is faulty or excessive.
In my case, I was still getting the error despite having specified the controller to test in #WebMvcTest(FooController.class).
I eventually realised it was due to the #ComponentScan of my application being needlessly cluttered up. My Application.java was something like this:
#SpringBootApplication
#ComponentScan({"fr.nevechris.projectname","fr.nevechris.projectname.otherpackage"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I removed the #ComponentScan entirely and the issue was solved.
If your #ComponentScan is good or not specified, try searching for other places in your project where configuration is done (eg #Configuration tag).

Integrate vertex with existing spring web application

I have an existing Spring based web application. I want to integrate vertx within the application.
Is there a way to do so?
Yes, have a look at the Vert.x with Spring section in the examples repository on GitHub.
In spring boot it is fairly simple
#SpringBootApplication
#ComponentScan(basePackages = { "com.mypackage", "com.myotherpackage" })
public class MyApplication {
#Autowired
private MainVerticle mainVertical;
public static void main(String[] args) throws Exception {
new SpringApplication(MyApplication.class).run(args);
}
#PostConstruct
public void deployServerVerticle() {
Vertx.vertx().deployVerticle(mainVertical);
}
}
The #PostConstuct allows you to deploy all the verticals you want (all the properties are set at this point).
And it goes without saying that the MainVerticle should be marked with the #Component annotation.

404 fail while trying to run spring boot app from start.spring.io

When I'm starting my mini project in spring boot (which mostly I generated from start.spring.io) from command line by command mvn spring-boot:run and walk to the http://localhost:8080/test/{michal} I see the 404 fail.
Beside that I can't create return statement in controller class using Response.create -> it shows:
The method create(String) is undefined for the type Response
I think this is the main problem why my app doesn't want to run properly.
This is my controller class
#RestController
public class TestController {
#Autowired
private TestService testService;
#RequestMapping(value = "/test/{name}", method = RequestMethod.GET)
public Response<String> /*#ResponseBody String*/ getWelcomeText(#PathVariable("name") String name) {
return Response.create(testService.loadWelcomeText(name));
}
}
This is my service class
#Service
public class TestService {
public String loadWelcomeText(String name) {
return "Hello " + name;
}
}
I have #ComponentScan annotation
It's like this: I have #ComponentScan annotation
How it looks in my project
Update
Looking at package layout you need to add #ComponentScan("com.bielawski.michal") annotation on your main class to tell spring-boot where to locate controller and service (or move main class to com.bielawski.michal package).
I think the problem is your use of Response instead of ResponseEntity. Not sure where you got documentation that said to use Response but the official documentation describes it here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-httpentity
Constructors for using ReponseEntity are: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html

Spring boot No WebApplicationContext found

I have a simple spring boot app and I'm trying to get it up and running. The config consists of an app context ( applicationContext.xml) XML with a bunch of beans in it. I have a Spring application class:
#SpringBootApplication
#Configuration
#ImportResource("classpath:applicationContext.xml")
public class WebCheckApplication {
private static final Logger logger = Logger.getLogger(WebCheckApplication.class);
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(WebCheckApplication.class, args);
if (logger.isDebugEnabled()) {
logger.debug("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
logger.debug(beanName);
}
}
}
}
And I have a #WebListener class that grabs a few beans from the WebContext from within the ServletContext:
#WebListener
public class SystemPropertiesContextInitializer extends SysPropsAlertsFetcher implements ServletContextListener {
private static final Logger logger = Logger.getLogger(SystemPropertiesContextInitializer.class);
#Override
public void contextDestroyed(ServletContextEvent sce) {
//remove the SystemProperties and alert types map object from context
sce.getServletContext().removeAttribute(BaseAuthenticatedController.SYSPROPS_KEY);
sce.getServletContext().removeAttribute(BaseAuthenticatedController.ALERT_TYPES_MAP_KEY);
}
#Override
public void contextInitialized(ServletContextEvent sce) {
SysPropsDataAccess = (SystemPropertiesDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("SystemPropertiesDataAccess");
AlertsDataAccess = (AlertDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("AlertsDataAccess");
fetchObjects(sce.getServletContext());
}
}
When I attempt to start the app, I get the following error:
SEVERE: Exception sending context initialized event to listener instance of class web.SystemPropertiesContextInitializer
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:83)
at .web.SystemPropertiesContextInitializer.contextInitialized(SystemPropertiesContextInitializer.java:31)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4994)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
and it occurs at this line:
SysPropsDataAccess = (SystemPropertiesDataAccess) WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getBean("SystemPropertiesDataAccess");
It looks like Spring isn't creating a WebApplicationContext.
Greater than or equal 1.3.0.RC1 use #ServletComponentScan
#ServletComponentScan // <-- This scans for EJB #WebFilter, #WebListener and #WebServlet
#SpringBootApplication
#ImportResource("classpath:applicationContext.xml")
public class WebCheckApplication {
Less than or equal 1.2.x use #Component to scan for listener
#Component // <-- This allows the component to be found by #ComponentScan inside of #SpringBootApplication
#WebListener
public class MojoSystemPropertiesContextInitializer extends MojoSysPropsAlertsFetcher implements ServletContextListener {
War Deploy extend SpringBootServletInitializer
public class WebCheckApplication extends SpringBootServletInitializer {
In 1.3.0.RC1 #ServletComponentScan was added so simply annotating your main application config should allow these to be picked up. Otherwise adding #Component to your ServletContextListener should work
This link is a discussion on how they currently handle #WebFilter how they decided to handle #WebFilter and they also discuss SpringBootServletInitializer and how this would pick process each item twice if both were to be used. Also links to the commits that implement the new feature.
https://github.com/spring-projects/spring-boot/issues/2290
If you intend to deploy your application as a war file you may also have your main configuration extend SpringBootServletInitializer
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html
All that was needed was to make the Application class extend SpringBootServletInitializer

Resources