How to redirect any url that do not match any #RequestMapping parameter in the application - spring

I use Spring MVC in my web application. I am trying to redirect any url that match the pattern http://localhost:8080/my-app/* to a specific controller. But if the url is something like the following, http://localhost:8080/my-app/test and if there is a controller as follows:
#Controller
#RequestMapping("test")
public class TestClass
{
#RequestMapping(value = "/landing", method = RequestMethod.GET)
public String selectHomePage(ModelMap model)
{
//do something
}
#RequestMapping(value = "/list", method = RequestMethod.GET)
public String listFaqCollections(#ModelAttribute("ownedby") String ownedBy, ModelMap model)
{
//do something
}
}
And I have another class as follows:
#Controller
public class InvalidUrslRedirect
{
#RequestMapping(method = RequestMethod.GET)
public String redirectInvalidUrls(Model model)
{
//do something
}
All the urls that are invalid will be redirected to the above controller class.
The valid urls would be as follows:
http://localhost:8080/my-app/test/landing
http://localhost:8080/my-app/test/list?ownedby=me
But if the url is something like:
http://localhost:8080/my-app/test/list?ownedbys=me
the normal tomcat 404 error page is displayed and the it is not getting redirected to the InvalidUrslRedirect class
In my web.xml file, I have the following:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/core/root-context.xml, classpath:spring/core/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In the spring-security.xml, I have:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/**" access="isFullyAuthenticated()"/>
I have been searching the net for some time now, but could not find much help. is there any way i can achieve such a functionality. Thanks in advance

If i understood you correctly, you want to redirect every request other than e.g. "/test". In this case you'll need two methods:
#RequestMapping(method = RequestMethod.GET)
public String redirectEverythingOtherThanTest(){
return "redirect:/pageToRedirectTo.html"
}
#RequestMapping(value="/test", method = RequestMethod.GET)
public String testRequest(){
//some stuff
return "somepage.html";
}
Also remember about #Controller annotation on your class.

How is your web application setup? Which URLs is Spring looking for? Do you have an AbstractAnnotationConfigDispatcherServletInitializer?
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Configure Spring MVC to handle ALL requests
*/
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
....
}
#Override
protected Class<?>[] getServletConfigClasses() {
....
}
#Override
public void onStartup(ServletContext container) throws ServletException {
...
}
}

Related

How to have jersey inject a param based on the http header?

I have an interface and would like to open it as a REST API.
Interface:
string createToken(String username, String scopes);
REST web API:
#GET
#Path("/createToken")
#Override
public string createToken(#InjectParam String username, String scopes) {
...
}
As a simple Java API,, the interface itself makes sense - creating an access token by a specific (unique) user.
But, as an REST web API, I need a previous step to retrieve the username, based on some user data that is passed in the http header, like an SSO key.
How do I inject a value into the username - extracted from the HTTP header? Thanks.
Created a Provider to inject the value into a custom annotation. See small working example here. See source inline below as well.
The example extracts the username from an sso token. It's a dummy extraction.
* I didn't use #InjectParam.
Invocation example:
curl -X POST -H "ssoToken: 1234" http://localhost:8080/JerseyCustomParamInjection-1.0-SNAPSHOT/oauth2/createAccessToken
Custom annotation:
#Target({ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface LoggedUser {
}
Provider to do the injection:
#Provider
public class LoggedUserProvider implements
Injectable<String>,
InjectableProvider<LoggedUser, Parameter> {
#Context
private HttpServletRequest request;
public LoggedUserProvider() {
}
#Override
public Injectable<String> getInjectable(ComponentContext cc, LoggedUser a, com.sun.jersey.api.model.Parameter c) {
return this;
}
#Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
#Override
public String getValue() {
String sso = request.getHeader("ssoToken");
if (sso == null) {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
// Retreive username from soo
String username = " <extracted username from sso="+sso+">";
return username;
}
}
Resource that defines the wants to inject the value:
#Path("/oauth2")
public class Resource {
#POST
#Path("/createAccessToken")
public String createAccessToken(
#LoggedUser String username
) {
return username + " <created access token using the logged in injected username>";
}
}
Servlet configuration (web.xml):
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>info.fastpace.jerseycustomparaminjection</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
You should use HeaderParam. See this
#GET
#Path("/createToken")
#Override
public string createToken(#HeaderParam("username") String username, String scopes) {
...
}
If you have to extract username and have to inject it, you will have to implement a provider:
#Provider
public class UsernameProvider
extends AbstractHttpContextInjectable<Locale>
implements InjectableProvider<Context, Type> {
#Override
public Injectable<E> getInjectable(ComponentContext compCntxt, Context cntxt, Type typ) {
if (typ.equals(String.class)) {
return this;
}
return null;
}
#Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
#Override
public String getValue(HttpContext httpCntxt) {
final Request rqst = httpCntxt.getRequest();
String username = null;
//Extract 'username' from Headers
return username;
}
}
Detailed explanation here

Jersey custom ExceptionMapper not called on 400 Bad Request (when validation fails)

I'm using Jersey with Spring for web services. For catching exceptions and formatting the response sent to the caller I have added an implementation of ExceptionMapper.
Though it is being called when I explicitly throw an exception from within the controller, but when the json field validation fails the exception mapper is not called and the response sent is **may not be null (path = checkNotification.arg0.tyres, invalidValue = null)
**
#Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
System.out.println("Exception Mapper !!!");
return Response.status(404).entity(ex.getMessage()).type("application/json").build();
}
}
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
com.help.rest.controller,
com.fasterxml.jackson.jaxrs.json
</param-value>
</init-param>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.help.filter.FeatureRegistration</param-value>
</init-param>
<init-param>
<param-name>jersey.config.beanValidation.enableOutputValidationErrorEntity.server</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Jersey Version is 2.22.1
Spring Version is 4.2.4
I made it work by changing
#Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
System.out.println("Exception Mapper !!!");
return Response.status(404).entity(ex.getMessage()).type("application/json").build();
}
}
to
#Provider
public class GenericExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException ex) {
System.out.println("Exception Mapper !!!");
return Response.status(404).entity(ex.getMessage()).type("application/json").build();
}
}
Though I'm able to catch the exception I am not getting the exact class and field which failed the constraint.
Resolved
Found a Set containing all the required fields in ContraintViolationException, could be accessed using ex.getConstraintViolations()
made it work by changing
#Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
System.out.println("Exception Mapper !!!");
return Response.status(404).entity(ex.getMessage()).type("application/json").build();
}
}
to
#Provider
public class GenericExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException ex) {
System.out.println("Exception Mapper !!!");
return Response.status(404).entity(ex.getMessage()).type("application/json").build();
}
}
To get the exact exception details, like which field failed the constraint use ConstraintViolationException's getConstraintViolations(). This method provides a set for all the constraint violations.
You need to register it:
public class MyApplication extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(HelloWorldResource.class);
/** you need to add ExceptionMapper class as well **/
s.add(GenericExceptionMapper.class)
return s;
}
}

Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext

I am using Spring MVC,google app engine, admin sdk, cloud sql.
I want to access (preferncesDao) dao class into Filter.
Below is my filter
public class NameSpaceGoogleSecurityFilter implements Filter
{
#Autowired
IPreferencesDao preferncesDao;
public void init( FilterConfig filterConfig ) throws ServletException{
SpringUtils.init(filterConfig.getServletContext());
preferncesDao = SpringUtils.getPreferncesDao();
}
}
Below is my SpringUtils class.
public class SpringUtils {
private static ApplicationContext appContext;
private static IPreferencesDao preferncesDao = null;
public static void init(final ServletConfig config) {
init(config.getServletContext());
}
public static void init(final ServletContext context) {
if(appContext==null){
appContext =
(ApplicationContext) context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
}
}
public static IPreferencesDao getPreferncesDao() {
if(preferncesDao==null){
preferncesDao=(IPreferencesDao) appContext.getBean("preferncesDao");
}
return preferncesDao;
}
protected SpringUtils() {
throw new UnsupportedOperationException();
}
}
When I start build process, It is throwing below exception
Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext
java.lang.NullPointerException.
Nullpointer at line preferncesDao=(IPreferencesDao) appContext.getBean("preferncesDao");
How can i resolve above error ? is it right way to get dao object into filter ? if not what is correct way.?
It is required to add below tag in web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
That purely indicate that ContextLoaderListener missing.
so add below code in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
For more details refer this link

Liferay 6.2 + Spring #Autowired not working in a hook

I am using Spring 4.0.6 with Liferay 6.2. Spring isn't able to inject autowired components in to the hook, object comes as null. I have also tried with spring version 3.1 that comes with liferay. Same code works in portlets but not in hooks.
private ApplicationEventPublisher publisher in ActivityEventPublisher.java is null.
web.xml
<?xml version="1.0"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web- app_2_4.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.liferay.portal.kernel.servlet.SecurePluginContextListener</listener- class>
</listener>
<listener>
<listener-class>com.liferay.portal.kernel.servlet.PortletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
</web-app>
ActivityEventPublisher.java
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import connect.activity.solr.document.ActivityData;
#Component
public class ActivityEventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
#Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public ApplicationEventPublisher getPublisher() {
return publisher;
}
public void setPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void publish(ActivityData data) {
ActivityEvent event = new ActivityEvent(this);
event.setActivityData(data);
this.publisher.publishEvent(event);
}
}
Any help will be much appreciated.
Thanks
Unfortunately, autowired mechanisms are not allowed in hooks, wrappers or startup actions at Liferay.
You can implement an ApplicationContextProvider, it's so easy and useful:
#Component("applicationContextProvider")
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx = null;
public static ApplicationContext getApplicationContext() {
return ctx;
}
#Override
public void setApplicationContext(ApplicationContext ac) throws BeansException {
ctx = ac;
}
}
An example of use in a Hook will be the following:
public class PostLoginActionHook extends Action {
// That code "replaces" #Autowired annotation
private final UserProxyService userProxyService = (UserProxyService) ApplicationContextProvider.
getApplicationContext().getBean(UserProxyService.class);
#Override
public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException {
UserVO myCustomUser = userProxyService.getCustomUserByLiferayUser(user.getUserId());
{...}
}
Hope it helps!

getting empty form session bean in jsf

I have set session bean after login, and print the value from session bean it prints in xhtml file but while i go to the next page or bean session bean return empty it automatically reset the value.
I am using the primeface 4.0, jsf 2.0 and ejb 3.0 for web application.
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value> </context-param> -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>ui-lightness</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.VIEW_UNIQUE_IDS_CACHE_ENABLED</param-name>
<param-value>true</param-value>
</context-param>
<mime-mapping>
<extension>xlsx</extension>
<mime-type>text/xlsx</mime-type>
</mime-mapping>
</web-app>
//Setting user from loginMB having viewscope bean.
UserMB
#SessionScoped
#ManagedBean(name = "userMB")
public class UserMB extends AbstractMB implements Serializable {
public static final String INJECTION_NAME = "#{userMB}";
private static final long serialVersionUID = 1L;
private User user;
#EJB
private UserEJB userEJB;
public String logOut() {
getRequest().getSession().invalidate();
return "/index.xhtml?faces-redirect=true";
}
private HttpServletRequest getRequest() {
return (HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest();
}
public User getUser() {
if (user == null) {
user = new User();
}
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<User> getUserList() {
if (userList == null) {
userList = userEJB.findAll();
}
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
}
CampMB
#ManagedBean
#ViewScoped
public class CampMB extends AbstractMB implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty("#{userMB}")
private UserMB userMB;
public UserMB getUserMB() {
return userMB;
}
public void setUserMB(UserMB userMB) {
this.userMB = userMB;
}
private User user;
private Camp camp;
private List<CampDTO> listCamp;
#EJB
private CampEJB campEJB;
#EJB
private MemberEJB memberEJB;
#EJB
private CodeValueEJB codeEJB;
TimeZone timeZone = TimeZone.getDefault();
public TimeZone getTimeZone() {
return timeZone;
}
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
public List<CampDTO> getListCamp() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
UserMB managedBean = (UserMB) sessionMap.get("userMB");
System.out.println("test use==" + managedBean.getUser().getId());
System.err.println("Session"+getUserMB().getUser().getId());
if (listCamp == null) {
listCamp = new ArrayList<CampDTO>();
}
listCamp = ConvertUtils.convertCampToDTO(campEJB.findAll());
return listCamp;
}
public void setListCamp(List<CampDTO> listCamp) {
this.listCamp = listCamp;
}
public User getUser() {
if (user == null) {
user = new User();
}
return user;
}
public void setUser(User user) {
this.user = user;
}
}
I am trying different techniques getting from search but no one works for me?
Is there any configuration for it or how to set/get session bean properly.

Resources