spring boot with sitemesh - spring-boot

I'm using spring boot, and I would like to use sitemesh3 to my project.
I need to add the sitemesh filter, I create this class :
#Configuration
public class Initializer implements ServletContextInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
//Sitemesh
FilterRegistration.Dynamic sitemesh = servletContext.addFilter("sitemesh", new ConfigurableSiteMeshFilter());
EnumSet<DispatcherType> sitemeshDispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
sitemesh.addMappingForUrlPatterns(sitemeshDispatcherTypes, true, "*.jsp");
}
}
I created the file sitemesh3.xml in WEB-INF directory but nothing happened, have I missed some configuration?

ServletContextInitializers aren't picked up with Spring Boot. Add the filter to your application configuration and wrap it in a FilterRegistrationBean.
See the Spring Boot reference guide.

Related

Why Servlet Filter can be Spring Bean?

What i know about Filter and Interceptor is that Filters as J2EE Specifications are part of the webserver and not the Spring framework. So some older articles explain that it is impossible to register filters as Spring Bean while Interceptor is possible.
But the results I got when I tested today is that Filters can be Spring Bean and also inject Spring Bean on Filters are possible too like Interceptors.
(I tested on SpringBoot Framework)
#Component
public class CustomFilterTest implements Filter {
#Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws ServletException, IOException {
chain.doFilter(request, response);
}
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
#Override
public void destroy() {
Filter.super.destroy();
}
}
#RestController
#RequiredArgsConstructor
public class ProductController {
private final CustomFilterTest customFilterTest;
#GetMapping("/test")
public ResponseEntity<Void> temp() {
System.out.println(customFilterTest);
return ResponseEntity.noContent().build();
}
}
Can anyone please explain to me?
We have to make a distinction between a regular Spring application and a Spring Boot application here. As with both, you can register a servlet filter as a bean, but the mechanism is a bit different.
Spring Framework
In plain Spring use the DelegatingFilterProxy to achieve this. The task of the DelegatingFilterProxy is to look for a bean with the same name as the filter in the root application context (the ApplicationContext registered through the ContextLoaderListener). This bean has to be your managed servlet filter.
#Configuration
#EnableWebMvc
public class WebConfiguration {
#Bean
public void YourFilter myFilter() { ... }
}
Then for the web application you would register a DelegatingFilterProxy with the name myFilter to make this work.
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public void onStartup(ServletContext servletContext)
throws ServletException {
super.onStartup(servletContext);
servletContext.addFilter("myFilter", DelegatingFilterProxy.class);
}
Spring Boot
In Spring Boot it is a bit different as Spring Boot is also in control of your servlet container, like Tomcat. It basically means that Tomcat is also a managed bean in your ApplicationContext and Spring Boot can inject dependencies into it. So when Spring Boot detects a bean for the servlet filter it will automatically add it to the filter chain (without the need of a DelegatingFilterProxy).
Which means only an #Bean for your filter is needed.
#Configuration
public class WebConfiguration {
#Bean
public YourFilter myFilter() { ... }
}
Additionally you can configure things like URLs etc. by adding an additional FilterRegistrationBean for this filter.
Conclusion
For plain Spring the DelegatingFilterProxy has been around since Spring 1.2 which was released in 2005. This means if you are reading really, really, really old articles (before 2005) this was true, however with the addition of the DelegatingFilterProxy, this isn't anymore. With the release of Spring Boot, this became even a lesser issue, is it more or less is the only way to register a filter (as a managed bean).

Make websocket (sockjs) work with spring4 running at GlassFish 3.1.2.2

I try to create websocket connection using sockjs on client and spring4 (with java config) on backend under GlassFish 3.1.2.2 but whatever I do it always fail with the following problem:
java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
However it works correctly under Tomcat without any error.
Is there a way to make this work under GlassFish 3.1.2.2? Or should I rewrite Spring java config back to web.xml style? If yes, can somebody show me an example?
Thank you.
I already enabled websocket in http protocol configuration in GlassFish manager and set
dynamic.setAsyncSupported(true);
in the WebApplicationInitializer.
#Configuration
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(IdCardReaderWebsocketApp.class);
ctx.setServletContext(servletContext);
final Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.setLoadOnStartup(2);
dynamic.addMapping("/sockjs/*");
dynamic.setAsyncSupported(true);
}
}
#Configuration
#ComponentScan("com.something.websocket.idcardreader.mock")
#EnableWebMvc
#Import({ IdCardReaderWebsocketConfig.class })
public class IdCardReaderWebsocketApp extends WebMvcConfigurerAdapter {
}
#Configuration
#EnableWebSocketMessageBroker
public class IdCardReaderWebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint("/idCardReaderWebsocketMockEndpoint").setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(final MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/mockApp");
registry.enableSimpleBroker("/idcard");
}
}
Ok, finally I fixed the issue. I had also web.xml file with an other filter. So I added
<async-supported>true</async-supported>
to that filter and problem solved. It still failes with ws:// protocol but at least it works with http when sockjs trying.

How to define #ComponentScan without XML and Annotation

How to Define ComponentScan Without Using annotation or Using XML in Spring? Is there any way to set componentScan using java code?
This blog says:
With the WebApplicationInitializer, Spring Framework Web MVC
applications can now rid themselves of web.xml. Additional
configuration/implementations are available for programmatically
registering the DispatcherServlet and configuring the Spring container
You should be using something like this:
public class Initializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.scan("com.package.name");
//the rest of initialization
}
}

Spring Boot + Mybatis #MapperScan and SqlSessionFactory

Im developing a new app using Spring Boot. I use Mybatis for persistance. Im using Java Config for everything I can.
I'm getting this exception when the app starts regarding creating my Mybatis mapper interface
exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
My Sring Boot application class is set up like this
#SpringBootApplication
#MapperScan("com.mydomain.admin.service.dao")
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class, args);
}
}
The Mybatis mapper interface class is set up like this
package com.mydomain.admin.service.dao;
public interface AdminClientDAO {
#Select("SELECT clientId, name, enabledFlag as enabled, dateAdded, dateUpdated as updateDate FROM client")
public List<Client> findAll();
}
my datasource is configured with spring boot. I've named the properties
spring.datasource.* so spring boot with auto-configure the data source
Now, Im wondering if Im assuming too much spring boot magic. I assumed that spring boot would configure the sqlSessionFactory because mybatis was in the classpath..
Many examples I see show configuring the sqlSessionFactory as a #Bean in the Java Config.. Is this the way it should be done is should spring boot be doing some magic and auto-config it?
I found my issue. I was missing mybatis-spring-boot-starter
I have
#Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
return sessionFactory.getObject();
}
In class called Application.java which extends
org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
And my Application.java is initialized in class which extends
org.springframework.boot.context.web.SpringBootServletInitializer
And the datasource works fine in my Spring-Boot Application.
Hope this helps somebody searching for Spring Boot, Mybatis and SQLSessionFactory with datasource in spring.datasource.*

How to enable async supported for a spring MVC application in java configuration file (Not XML)

I know how to enable async support in a XML configuration, I have done so for filters and servlets by adding tag
async-supported>true/async-supported
How to do it in a Java config file. I create a WebInit class which implements WebApplicationInitializer and overrides onStartUp -what should I do next?
public class WebInit implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
//What to do here, to move from XML to java config
}
}
Along the following lines -
ServletRegistration.Dynamic registration = container.addServlet(servletName, myServlet);
registration.setAsyncSupported(true);
EDIT:
Sorry, did not realize that you were looking for a Spring specific solution. With Spring MVC you would just extend a AbstractAnnotationConfigDispatcherServletInitializer assuming that your root and web contexts are #Configuration based. This initializer in-turn extends from AbstractDispatcherServletInitializer, this class has asyncSupported flag set by default.

Resources