Spring static resource mapping does not work - spring

i am trying to create a Spring MVC application with security included. All configuration is made in code, no XML-s. First, i have my WebApplicationInitializer, mapping all requests to my dispatchservlet:
public class DBCAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(DBCConfiguration.class);
ctx.setServletContext(servletContext);
ServletRegistration.Dynamic servlet = servletContext.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
servlet.setMultipartConfig(new MultipartConfigElement("", 1024*1024*5, 1024*1024*5*5, 1024*1024));
}
Also there is a config file:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "our.dbc")
public class DBCConfiguration extends WebMvcConfigurerAdapter {
private static final Logger log = Logger.getLogger(DBCConfiguration.class);
#Bean
public InternalResourceViewResolver getInternalResourceViewResolverJsp(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(0);
log.info("#### Internal view resolver 0 called...");
return viewResolver;
}
#Bean
public StandardServletMultipartResolver multipartResolver(){
log.info("#### Multipart resolver called...");
return new StandardServletMultipartResolver();
}
// #Override
// public void addResourceHandlers(final ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/resources/**")
// .addResourceLocations("/resources/");
//
// }
//
// #Override
// public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// configurer.enable();
// }
}
As you can see, i have tried both addResourceHandler and configureDefaultServletHandling, but none of those worked. Problem is that all request by default, with lowest priority end up returing welcome page (so if bad address requested, welcome is returned :), so that instead of getting the css client gets back to welcome page:
#Controller
public class FileUploadController {
private static final Logger LOG = Logger.getLogger(FileUploadController.class);
private static final String FORM = "form";
private static final String WELCOME = "welcome";
private static final String DENIED = "accessDenied";
private static final String UPLOADED_REDIRECT = "redirect:/uploaded";
#Autowired
FileUploadService uploadService;
#RequestMapping(value = "/**", method = RequestMethod.GET)
public String getWelcome() {
return WELCOME;
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage() {
LOG.info("#### /login called..." );
return "login";
}
#RequestMapping(value = { "/uploaded" }, method = RequestMethod.GET)
public String getUploaded() {
LOG.info("#### /uploaded called..." );
return "uploaded";
}
.
.
.
As i said, i also have security configured, but with default container servlet serving static resources, it whould not have to be changed. Anyway, i tried also to add permitall to resources, but no success. Anyway if i disable security it does not work either, so security is not the problem.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/welcome").permitAll()
.antMatchers("/form").access("hasRole('ADMIN')and hasRole('USER')")
.
.
.
But no chances. If i type http://localhost:8080/SpringMVC/resources/app.css instead of getting the stylesheet, browser gets back to welcome page.
Any suggestions? Any help whould be appreciated :)

Related

Adding custom header to response in spring rest / spring boot

i am trying to send session id in response header in rest controller but excludepathpattern() seems not working
** the configuration class is not triggering **
i have tried changing the sevlet version but it didnt work
ContextListener
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
Map<String, HttpSession> map = new HashMap<>();
context.setAttribute("activeUsers", map);
HttpSessionListener
ServletContext context = session.getServletContext();
Map<String, HttpSession> activeUsers = (Map<String, HttpSession>) context.getAttribute("activeUsers");
activeUsers.put(session.getId(), session);
HandlerInterceptor
ServletContext context = request.getServletContext();
Map<String, HttpSession> activeUsers = (Map<String, HttpSession>) context.getAttribute("activeUsers");
String sessionId = request.getHeader("sessionId");
String requestUrl = request.getRequestURL().toString();
if (requestUrl.contains("/getOtp") || requestUrl.contains("/validateOtp")) {
return true;
} else {
if (activeUsers.containsKey(sessionId)) {
return true;
} else {
response.setStatus(401);
return false;
}
}
interceptorconfigurartion by extendig websecurityconfigure
#Configuration
#EnableAutoConfiguration
public class SessionInterceptorConfig implements WebMvcConfigurer {
#Autowired
private SessionHanlderInterceptor sessionHandlerIntercepto;
#Override
public void addInterceptors(InterceptorRegistry registry) {
// List<String> paths = new ArrayList<String>();
// paths.add("/auth/*");
registry.addInterceptor(sessionHandlerIntercepto).excludePathPatterns("/auth/**");
}
#Bean
public ServletListenerRegistrationBean<CustomSessionListener> filterRegistrationBean() {
ServletListenerRegistrationBean<CustomSessionListener> registrationBean = new ServletListenerRegistrationBean<CustomSessionListener>();
CustomSessionListener customURLFilter = new CustomSessionListener();
registrationBean.setListener(customURLFilter);
registrationBean.setOrder(1); // set precedence
return registrationBean;
}
#Bean
public ServletListenerRegistrationBean<CustomServletContextListener> filterContextRregistration() {
ServletListenerRegistrationBean<CustomServletContextListener> registrationBean = new ServletListenerRegistrationBean<CustomServletContextListener>();
CustomServletContextListener customURLFilter = new CustomServletContextListener();
registrationBean.setListener(customURLFilter);
registrationBean.setOrder(1); // set precedence
return registrationBean;
}
Sprinboot main class
#SpringBootApplication
public class CustomerApplication extends SpringBootServletInitializer {
i expect to add the session id to header in response and to check for the sessionid in request
You can use spring web component "OncePerRequestFilter". You need to inject a bean which extends OncePerRequestFilter. Example:
public class CustomHeaderFilter extends OncePerRequestFilter {
#Override
public void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain chain) throws IOException, ServletException {
response.setHeader(customHeaderName, customHeaderValue);
chain.doFilter(request, response);
}
}

Spring Boot + JSF static page configurations

am getting started with Spring Boot + JSF.
Spring documentation says:
Spring will automatically load and serve resources inside
/static (or /public or /resources or /META-INF/resources.
This is not working for me.
it is discouraged to use the "webapp" (src/main/webapp) folder.
But for my static content, it seem to be the only folder thats working with my JSF static page.
see Spring Boot static content.
I have tried these configuration:
#Configuration
public class JSFServletConfigs implements ServletContextInitializer// ,ServletContextAware
{
#Override // ServletContext initiallization parameters
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("facelets.DEVELOPMENT", "false");
servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development");
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("javax.faces.PARTIAL_STATE_SAVING_METHOD", "true");
servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "-1");
}
#Bean // Registering the FacesServlet.
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(servlet) {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
FacesInitializer facesInitializer = new FacesInitializer();
Set<Class<?>> clazz = new HashSet<Class<?>>();
clazz.add(JSFServletConfigs.class);
facesInitializer.onStartup(clazz, servletContext);
}
};
servletRegistrationBean.addUrlMappings("*.xhtml", "*.jsf", "*.html");
return servletRegistrationBean;
}
#Bean
public InternalResourceViewResolver jsfViewResolving(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/<sub-folder of any LOCATION>/");
viewResolver.setSuffix(".xhtml");
return viewResolver;
}
}
Servlet pre-configs:
#Configuration
#EnableWebMvc
public class DefaultServletConfigs extends WebMvcConfigurerAdapter {
#Override // Enabling the default Servlet at path="/"
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
private final String[] LOCATIONS = {"<All my possible locations>"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if(!registry.hasMappingForPattern("/**")){
registry.addResourceHandler("/**").addResourceLocations(LOCATIONS);
}
if(!registry.hasMappingForPattern("webjars")){
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
}
My Question are:
What am I missing here?
How do I get the flexibility to place my resources in any of the other folders above
(i.e. "/static", "/public", "/resources", "/META-INF/resources").

How to get the session object in general from within a class?

There is a class :
#Configuration
#ComponentScan("com.ambre.pta")
#EnableTransactionManagement
#PropertySources({
#PropertySource("classpath:fr/global.properties"),
#PropertySource("classpath:fr/main.properties"),
#PropertySource("classpath:fr/admin.properties"),
#PropertySource("classpath:fr/referentiel.properties"),
#PropertySource("classpath:fr/departement.properties"),
#PropertySource("classpath:fr/exercice.properties"),
#PropertySource("classpath:fr/defi.properties")
})
public class ApplicationContextConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
bds.setUrl("jdbc:oracle:thin:#localhost:1521:xe");
bds.setUsername("pta");
bds.setPassword("pta");
return bds;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages("com.ambre.pta.model");
return sessionBuilder.buildSessionFactory();
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
#Autowired
#Bean(name = "utilisateurDao")
public UtilisateurDAO getUtilisateurDao(SessionFactory sessionFactory) {
return new UtilisateurDAOImpl(sessionFactory);
}
}
We can get the request object within this class by this way :
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
So is there a way to get the session ( HttpSession ) object ?
Using Controller classes
You can define HttpSession as an argument to your controller methods:
#RequestMapping("/my-path")
public String doStuff(HttpSession session) {
// do stuff...
}
This is also the recommended way to access the HttpRequest, rather than going through RequestContextHolder, because it's easier to mock out the session for tests.
See the Spring MVC docs for more detail.
Without using controller classes
Another option is to use a #SessionScope bean and mutate it accordingly:
#Component
#SessionScope
public class MySessionScopedBean {
String attribute;
}
public class MyOtherClass {
#Autowired
private MySessionScopedBean myBean;
public void doStuff() {
// myBean accesses a bean instance isolated in the user session
myBean.attribute = "test";
}
}
If you want to access the HttpSession outside a Controller method, there are two possible answers:
Don't do it, it's evil.
If you really really want to do it (and I have done it in the past, so who am I to blame you), then the easiest way is to write a class to hold the session, and an interceptor to set and unset it. But to make things easier, I will be working with HttpServletRequest objects, from which you can extract the session:
public class RequestHolder {
private static final ThreadLocal<HttpServletRequest> REQUEST =
new ThreadLocal<>();
public static HttpServletRequest getCurrentRequest() {
return REQUEST.get();
}
public static HttpSession getCurrentSession() {
HttpServletRequest request = REQUEST.get();
return request == null ? null : request.getSession();
}
public static void setCurrentRequest(HttpServletRequest request) {
REQUEST.set(request);
}
public static void unsetCurrentRequest() {
REQUEST.remove();
}
}
public class RequestHolderInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) {
RequestHolder.setCurrentRequest(request);
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView mav) {
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e){
RequestHolder.unsetCurrentRequest();
}
}

The requested resource is not available when wanna map to .html file

I'm using Spring mvc, and wanna make web app which send some json data to client and client should visualized them using js.
I have some questions:
1-My project have some *.html beside *.jsp file how can I handle both without web.xml. the code that i had written work fine with *.jsp but give "The requested resource is not available." error for mapping html files.
2-As i said My service have to send a list of object in json form to client, when i want to parse the json string on server in *.jsp file with the code like
MyClass data = new Gson().fromJson(MyList.get(0).toString(), listType)
,I face with to many problems, so i decide to do this job in client Side in *.html file, i want to know how should i handle this parsing job when i don't want that client know about the structure my class? OR plz tell if have to share my class with client, how should i send stucture of it to html file?
3-How should i access to data that i created in restapi.jsp on the UserSideApp.html file?
these are some my files:
AppInitializer.java
public class AppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
} }
AppConfig.java
public class AppConfig {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix("");
return viewResolver;
} }
the part of my AppContoller.java
#Controller
#RequestMapping("/")
public class AppController {
#Autowired
HackDataService service;
#RequestMapping(value = "/restapi", method = RequestMethod.GET)
public String jsonAPI(ModelMap model) {
List<HackData> newList = service.findAllNewData();
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json="";
try {
json = ow.writeValueAsString(newList);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
model.addAttribute("List", json);
String newjson = new Gson().toJson(newList);
model.addAttribute("newList", newjson);
return "newTest.jsp";
}
#RequestMapping(value = "/app", method = RequestMethod.GET)
public String htmlapp() {
return "UserSideApp.html";
} }
and my both .html and .jsp files are in "/WEB-INF/views/"
After spending almost a day on first problem, i find the answer of it,
first of all instead of implementing WebApplicationInitializer, I extend AbstractAnnotationConfigDispatcherServletInitializer and for java Configing i extends WebMvcConfigurerAdapter.
Then i create a pages folder in WEB-INF and my codes changes to these:
AppInitializer became like other internet's samples.
AppConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.attackmap" })
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/WEB-INF/pages/");
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix("");
return viewResolver;
}
}
AppController.java
#Controller
#RequestMapping("/")
public class AppController {
#RequestMapping(value = { "/", "/info" }, method = RequestMethod.GET)
public String welcome(ModelMap model) {
model.addAttribute("message", "home page with info about site");
return "homepage.jsp";
}
#RequestMapping(value = "/finalapp", method = RequestMethod.GET)
public String test() {
return "redirect:/pages/final.htm";
} }
there was another way
Creating a "resources" directory in "src/main/webapp"
add bellow cod in AppConfig.java
registry.addResourceHandler("/WEB-INF/views/resources/*.html").addResourceLocations("/resources/");
and for viewResolving use the code like bellow:
#RequestMapping(value = "/newapp", method = RequestMethod.GET)
public String test2() {
return "/resources/UserSideAppNew.html";
}
but still my two other questions are unsolved, the main problem was first one but if you know sth, about these two plz tell me about them

How can i separate jsp in differents folders with Spring?

This is my AppInitializer:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.project.app")
public class AppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer implements
WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
And this is my AppConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.acfcm.app")
#Import({ SecurityConfig.class })
public class AppConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolverForClasses() {
ResourceBundleViewResolver viewResolver = new ResourceBundleViewResolver();
viewResolver.setOrder(1);
viewResolver.setBasename("views");
return viewResolver;
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setOrder(2);
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations(
"/resources/");
}
}
What I want is how to change the AppConfig to put .jsp in differents foldes into the project because right now only can save it in /WEB-INF/views/ and there is a lot of .jsp!! I want to have two more folders to see my project like:
WEB-INF/views/moduleOne/
WEB-INF/views/moduleTwo/
...
Thanks!
I think your code is all fine; it will look for your JSPs starting in /WEB-INF/views/
Most people do like you say and break up JSP views under folders like /admin, /common, etc.
The way you do this is to specify the subfolder in the controller. For example, in your controller, you could return:
#RequestMapping(value = "/admin/index.htm", method = RequestMethod.GET)
public ModelAndView index(HttpServletRequest request,
HttpServletResponse response)
{
Map<String, Object> myModel = new HashMap<String, Object>();
myModel.put("someValues", new ArrayList());
ModelAndView mv = new ModelAndView("admin/index","model", myModel);
return mv;
}
Doing it like the above, you can put your JSP under
/WEB-INF/views/admin/index.jsp
Of course, your mappings (/admin) doesn't have to match the directory structure (/WEB-INF/views/admin) but we chose to make both match, to make it faster to find the code (if controller mapping matches the dir structure).
The important thing to remember is that whatever you put in that ModelAndView first param, Spring will prepend and append the values you defined in your code:
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
So, if you return ModelAndview("/pierre/was/here/something"), Spring will try to find the JSP at location: "/WEB-INF/views/pierre/was/here/something.jsp"
The common practice is to have the configuration as yours, and in the request handler controller methods, use the view names as moduleOne/view1, moduleTwo/view2 etc.

Resources