The Scenario
When we were developing the admin backend, we split it into 2 projects: backend application using jax-rs jersey, front end with angularjs - following single app design principle.
Later we decide to merge these 2 into one project, and use Spring security to protect front side(web url, page section etc) and jersey jax-rs.
We prefer Spring Java config over xml because it's more flexible, and XML configuration is kind of black box to developers, using Java config, we can know more about the implementation and help us debug it later.
Update:
Later we upgrade to jersey 2:
Basically we configure two servlets:
Spring security is used to do authentication and authorization.
Jersery 1
Difference between / and /* in servlet mapping url pattern
http://javapapers.com/servlet/what-is-servlet-mapping/
When we were developing the admin backend, we split it into 2 projects: backend application using jax-rs jersey, front end with angularjs - following single app design principle.
Later we decide to merge these 2 into one project, and use Spring security to protect front side(web url, page section etc) and jersey jax-rs.
We prefer Spring Java config over xml because it's more flexible, and XML configuration is kind of black box to developers, using Java config, we can know more about the implementation and help us debug it later.
Update:
Later we upgrade to jersey 2:
@Priority(value = 1)
public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {MyAppConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
// this is to fix issues in jersey-srping3
// org.glassfish.jersey.server.spring.SpringWebApplicationInitializer
servletContext.setInitParameter("contextConfigLocation", "");
servletContext.addListener(RequestContextListener.class);
MyUtil.addDefaultUncaughtExceptionHandler();
}
@Override
protected WebApplicationContext createRootApplicationContext() {
final WebApplicationContext context = super.createRootApplicationContext();
final ConfigurableEnvironment env = (ConfigurableEnvironment) context.getEnvironment();
final String profile = (String) env.getSystemProperties().get("env");
env.setActiveProfiles(profile);
return context;
}
}
public class MySecurityInitializer extends AbstractSecurityWebApplicationInitializer {}
@WebServlet(loadOnStartup = 1)
@ApplicationPath("/v1/*")
public class MyJerseyApplication extends ResourceConfig {
public JerseyRestProvisionApplication() {
packages("the_package_xx");
property(ServerProperties.WADL_FEATURE_DISABLE, true);
register(JacksonFeature.class);
register(GZipEncoder.class);
register(MultiPartFeature.class);
register(new LoggingFilter(Logger.getLogger(MyJerseyApplication.class.getName()), true));
register(RequestContextFilter.class);
register(MyHttpHeaderFilter.class);
}
}
How ToBasically we configure two servlets:
- web.servlet.DispatcherServlet: map it to / (notice not /*). This handles Spring Security and Spring MVC.
- Jersey SpringServlet: map to v1(all rest API starts with v1/).
Spring security is used to do authentication and authorization.
Jersery 1
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(final ServletContext servletContext) {
final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
final ConfigurableEnvironment env = rootContext.getEnvironment();
final String profile = (String) env.getSystemProperties().get("env");
env.setActiveProfiles(profile);
servletContext.addListener(new ContextLoaderListener(rootContext));
addSpringServlet(servletContext, profile);
addSpringJersyServlet(servletContext, env);
}
protected void addSpringServlet(final ServletContext servletContext, final String profile) {
final DispatcherServlet dispatcherServlet = new DispatcherServlet(new GenericWebApplicationContext());
final Dynamic dispatcherDynamic = servletContext.addServlet("dispatcherServlet", dispatcherServlet);;
dispatcherDynamic.setLoadOnStartup(1);
dispatcherDynamic.addMapping("/");
servletContext
.addFilter(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME, DelegatingFilterProxy.class)
.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
}
protected void addSpringJersyServlet(final ServletContext servletContext, final ConfigurableEnvironment env) {
final ServletRegistration.Dynamic appServlet = servletContext.addServlet("jersey-servlet", new SpringServlet());
appServlet.setInitParameter(JSONConfiguration.FEATURE_POJO_MAPPING, "true");
appServlet.setInitParameter(ResourceConfig.FEATURE_TRACE, env.getProperty("jersey.enable.trace", "false"));
appServlet.setInitParameter(ResourceConfig.FEATURE_DISABLE_WADL,
env.getProperty("jersey.disable.wadl", "true"));
appServlet.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS,..);
appServlet.setInitParameter(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, ..);
appServlet.setLoadOnStartup(2);
appServlet.addMapping("/v1/*");
}
}
ResourcesDifference between / and /* in servlet mapping url pattern
http://javapapers.com/servlet/what-is-servlet-mapping/