When we deploy the spring boot application as a "war" on tomcat, we have to extend SpringBootServletInitializer and override the “configure” method.
When I comment "main" method, it still works and spring boot application and my services work fine. Do we still need main method when deploy project as "war" and why?
#SpringBootApplication
#EnableWs
public class TestApp extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder
builder) {
return builder.sources(TestApp.class);
}
public static void main(String[] args) {
SpringApplication.run(TestApp.class, args);
}
}
#SpringBootApplication
#EnableWs
public class TestApp extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder
builder) {
return builder.sources(TestApp.class);
}
/*public static void main(String[] args) {
SpringApplication.run(TestApp.class, args);
}*/
}
No you don't because nobody will ever call it.
Expect for the case if you want to run it outside of the web container.
Related
A normal spring-web application can be deployed to tomcat standalone as war file as follows:
#SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Question: how can I deploy such an application after migrating to spring-webflux to tomcat?
Docs say:
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-httphandler
To deploy as a WAR to any Servlet 3.1+ container, you can extend and
include AbstractReactiveWebInitializer in the WAR. That class wraps an
HttpHandler with ServletHttpHandlerAdapter and registers that as a
Servlet.
So but there is no example how to.
I tried as follows, which gives an exception:
#SpringBootApplication
public class MyApplication extends AbstractReactiveWebInitializer {
#Override
protected Class<?>[] getConfigClasses() {
return new Class[] {MyApplication.class};
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Result:
MyApplication.java:13:8
java: cannot access javax.servlet.ServletException
class file for javax.servlet.ServletException not found
This use case is not supported by the Spring Boot team, as explained in the reference documentation. Even if some features might work, you'll find many limitations and bugs to this approach - and it seems you've started to experience just this.
I have set the context path for tomcat as follows:
#Component
public class CustomContainer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
#Override
public void customize(TomcatServletWebServerFactory factory) {
factory.setContextPath("/capripol");
factory.setPort(8080);
}
}
Navigating to localhost:8080/capripol works fine and I am prompted with my login screen, however after logging in my forms and controllers do not append to the context path, so instead of navigating to /capripol/MainMenu etc. they navigate to /MainMenu. How do I set the context path such that my form actions and controllers will be appended do it - why is the tomcat factory context path not setting?
Edit: My Application class
#SpringBootApplication
public class CapripolApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(CapripolApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(CapripolApplication.class);
}
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/", "classpath:/images/")
.setCachePeriod(0);
}
}
}
A few ways to do it. You can add it to each controller, usefully if you want to change the context path
#Controller
#RequestMapping(value = "/foo")
public class bar{
#GetMapping(value = "/bar")
public void stuff(){
//doing stuff
}
}
Or you can put it in your application.properties / yml
server.servlet.contextPath=/foo/*
There are technically some other more round about ways to do it, especially if you are using an older version of Spring, but I would think the application properties is what you are looking for.
#SpringBootApplication
public class IFMApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(IFMApp.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(IFMApp.class);
}
}
I want to run above boot service program (IFMApp) through the command line (linux terminal).
The War/Jar files i built:-
1. ifmservice.war
2. ifmservice-jar-with-dependencies.jar
3. ifmservice-tests.jar
Help will be greatly appreciated. Thanks
Firstly ,go to your target folder in your project and then type in :
java -jar your_jar_Name
I have a Spring Boot app using SpringWS. Inside of the WsConfigurerAdapter I am overriding addInterceptors in order to add logging/authentication/validation/etc.
#Configuration
#EnableCaching
#EnableWs
public class WebServiceConfig extends WsConfigurerAdapter {
...
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
EnvironmentSettings environment = getEnvironmentSettings();
interceptors.add(getLogSetupInterceptor());
interceptors.add(getAuthenticationInterceptor());
interceptors.add(getServerLoggingInterceptor());
interceptors.add(getAuthorizationInterceptor());
ServerPayloadValidatingInterceptor validatingInterceptor = new ServerPayloadValidatingInterceptor();
validatingInterceptor.setValidateRequest(environment.isValidateSoapRequest());
validatingInterceptor.setValidateResponse(environment.isValidateSoapResponse());
validatingInterceptor.setXsdSchema( xsdSchema());
interceptors.add(validatingInterceptor);
}
}
What is strange is that when run locally, all of these interceptors are being added and run for every request just fine. However, when I deploy the application as a .war to WAS, this one method is not being run. I even added logging statements and I can tell that it's this method that's getting skipped over instead of the interceptors themselves. Does anybody know something about spring boot .war files that I don't?
Also, here is my Application class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I figured out what I did wrong. It turns out I was creating a servlet mapping in both my WebServiceConfig and my web.xml both at /*.
I used spring boot to do a sample service. It works fine when i run it using
"java -jar DemoLibrary.war" command in commandline. I get the proper message that "Library Application Has Started".
I did like below in Appplication.java file;
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
LogService.info(Application.class.getName(), "Library Application Has Started.");
}
}
When i run it in a external tomcat, it starts fine and works also fine. But i dont see the same message as it doesnot use that main method anymore. I just see spring application started message.
Is there a way i can change that message and give as i want?
Add an ApplicationListener<ContextRefreshedEvent> typed class and register it as a #Bean.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public ApplicationListener<ContextRefreshedEvent> startupLoggingListener() {
return new ApplicationListener<ContextRefreshedEvent>() {
public void onApplicationEvent(ContextRefreshedEvent event) {
LogService.info(Application.class.getName(), "Library Application Has Started.");
}
};
}
}
Something like this should work in both situations without duplicating code (although the code isn't complex but still).
You could use onStartup, something like:
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
LogService.info(Application.class.getName(), "Library Application Has Started.");
super.onStartup(servletContext);
}