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);
}
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.
I run the Spring boot in the different way , jar and war package to run the code.
I need to run some code in the filter init method, I run with jar ,it work.
However I run with war, it's order not right.
I want to know why and how to run in war get the result like run with jar way.
so , I write some code like these, and run in the different way , found it has different result.
SpringBootWebApplication.java
#ComponentScan(value = "com", excludeFilters = #ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class))
#SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer implements WebMvcConfigurer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBootWebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SpringBootWebApplication.class, args);
}
#Bean
public FilterRegistrationBean hrFilterRegistration() {
FilterRegistrationBean<TestFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new TestFilter());
registration.addUrlPatterns("/*");
registration.setName("testFiter");
registration.setOrder(1);
return registration;
}
}
TestBean.java
#Component
public class TestBean {
public static String aaa = "nothing";
public TestBean() {
System.out.println(aaa);
}
}
TestFilter.java
public class TestFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) {
TestBean.aaa = "good thing";
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
System.out.println("filter dofilter");
}
#Override
public void destroy() {
System.out.println("filter destory");
}
}
when I run with jar,I get the result:
good thing
when I run with war,I get the result:
nothing
I want to run with war, get the result:
good thing
The best way will be to use #Order annotation that can specify the order of running filters (but can be applied not only to filters)
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/annotation/Order.html
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.
I'm using Vaadin (7.6.1) with SpringBoot (1.3.0) and I got a problem regarding the application URL in the browser.
If I call "http://localhost:8080/myApp/" everything works fine -Spring Security blocks the request, redirects to login page, and after an authentication it calls the defaultSuccessUrl ("/#!"). But if the user calls "http://localhost:8080/myApp" (without the last slash) Spring Security also works but redirects to the savedRequestUrl. In this case an error message ("failed to load the bootstrap javascript: ./vaadin/vaadinbootstrap.js") is displayed.
Generally I want Spring Security to redirect to the savedRequestUrl, so what should I do? Does the URL pattern of the Servlet is beeing my problem? In this answer there is an example of an Annotation based WebServlet but if this is my problem how should I integrate it in my application?
I defined my own SpringVaadinServlet which overrides the default vaadinServlet bean. My classes look like this:
#SpringBootApplication
public class MyApp
{
public static void main(String[] args)
{
SpringApplication.run(MyApp.class, args);
}
#Bean(name = "vaadinServlet")
public CustomSpringVaadinServlet springVaadinServlet()
{
return new CustomSpringVaadinServlet();
}
}
public class ServletInitializer extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
[...]
return application.sources(MyApp.class);
}
}
public class CustomSpringVaadinServlet extends SpringVaadinServlet
{
private static final long serialVersionUID = -6507628193889155490L;
private final static Logger LOG = LoggerFactory.getLogger(SpringVaadinServletWsi.class);
#Override
protected void servletInitialized() throws ServletException
{
super.servletInitialized();
getService().setSystemMessagesProvider(new SystemMessagesProvider()
{
private static final long serialVersionUID = -5253418651979378723L;
#Override
public SystemMessages getSystemMessages(SystemMessagesInfo systemMessagesInfo)
{
CustomizedSystemMessages messages = new CustomizedSystemMessages();
messages.setCommunicationErrorCaption("Kommunikationsfehler");
[...]
return messages;
}
});
}
}