Hot questions for Spring Web Flow

Top 10 Java Open Source / Spring / Spring Web Flow

Question:

We are developing RESTful webservices with Spring 3 and we need to have the functionality of login/logout, something like /webservices/login/<username>/<password>/ and /webservices/logout. The session should be stored in the context until the session is timed out or logged out to allow consumption of other webservices. Any request to access webservices without session information should be rejected. Looking for state-of-the-art solution for this scenario.

I am actually resurrecting the question asked here Spring Security 3 programmatically login, which is still not properly answered. Please specify the changes needed in web.xml as well.


Answer:

I would suggest defining your Spring Security filters completely manually. It's not that difficult, and you get full control over your login/logout behaviour.

First of all, you will need standard web.xml blurb to delegate filter chain handling to Spring (remove async-supported if you are not on Servlet API ver 3):

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <async-supported>true</async-supported>
    <filter-class>
        org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>



<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Now, in security context you will define filters separately for each path. Filters can authenticate user, log out user, check security credentials etc.

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <sec:filter-chain-map path-type="ant">
        <sec:filter-chain pattern="/login" filters="sif,wsFilter"/>
        <sec:filter-chain pattern="/logout" filters="sif,logoutFilter" />
        <sec:filter-chain pattern="/rest/**" filters="sif,fsi"/>
    </sec:filter-chain-map>
</bean>

The XML above tells Spring to pass requests to specific context-relative URLs through filter chains. First thing in any of the filter chains is establishing security context - 'sif' bean takes care of that.

<bean id="sif" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>

Next filter in chain can now either add data to the security context (read: log in/log out user), or make a decision as to whether allow access based on said security context.

For your login URL you will want a filter that reads authentication data from the request, validates it, and in turn stores it in security context (which is stored in session):

<bean id="wsFilter" class="my.own.security.AuthenticationFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
  <property name="passwordParameter" value="pass"></property>
  <property name="usernameParameter" value="user"></property>
  <property name="postOnly" value="false"></property>

You can use Spring generic UsernamePasswordAuthenticationFilter but the reason I use my own implementation is to continue filter chain processing (default implementation assumes user will get redirected on successful auth and terminates filter chain), and being able to process authentication every time username and password is passed to it:

public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

@Override
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
    return ( StringUtils.hasText(obtainUsername(request)) && StringUtils.hasText(obtainPassword(request)) );
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
        Authentication authResult) throws IOException, ServletException{
    super.successfulAuthentication(request, response, chain, authResult);
    chain.doFilter(request, response);
}

You can add any number of your own filter implementations for /login path, such as authentication using HTTP basic auth header, digest header, or even extract username/pwd from the request body. Spring provides a bunch of filters for that.

I have my own auth success handler who overrides the default redirect strategy:

public class AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

   @PostConstruct
   public void afterPropertiesSet() {
       setRedirectStrategy(new NoRedirectStrategy());
   }

    protected class NoRedirectStrategy implements RedirectStrategy {

        @Override
        public void sendRedirect(HttpServletRequest request,
                HttpServletResponse response, String url) throws IOException {
            // no redirect

        }

    }

}

You don't have to have custom auth success handler (and probably custom auth filter as well) if you're ok with user being redirected after successful login (redirect URL can be customized, check docs)

Define authentication manager who will be responsible for retrieving user's details:

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="myAuthAuthProvider"/>
</sec:authentication-manager>

 <bean id="myAuthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService">
        <bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
            <property name="userDetailsService" ref="myUserDetailsImpl"/>
        </bean>
    </property>
</bean>

You will have to provide your own user details bean implementation here.

Logout filter: responsible for clearing security context

<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
        </list>
    </constructor-arg>
</bean>

Generic authentication stuff:

<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <property name="allowIfAllAbstainDecisions" value="false"/>
    <property name="decisionVoters">
        <list>
            <ref bean="roleVoter"/>
        </list>
    </property>
</bean>

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>

<bean id="securityContextHolderAwareRequestFilter" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>

Access control filter (should be self-explanatory):

<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="myAuthenticationManager"/>
    <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
    <property name="securityMetadataSource">
        <sec:filter-invocation-definition-source>
            <sec:intercept-url pattern="/rest/**" access="ROLE_REST"/>
        </sec:filter-invocation-definition-source>
    </property>
</bean>

You should also be able to secure your REST services with @Secured annotations on methods.

Context above was plucked from existing REST service webapp - sorry for any possible typos.

It is also possible to do at least most of what is implemented here by using stock sec Spring tags, but I prefer custom approach as that gives me most control.

Hope this at least gets you started.

Question:

I am working on a web app where I have most of my pages making use of apache tiles (2.1.2), but a few of them need to just be plain jsps.

I am having a problem in that both an InternalResourceViewResolver and a UrlBasedViewResolver will try to resolve the view no matter what, so that no matter which ordering I use, it will either fail on the plain JSP pages, or on the tiles pages.

Here is the config:

<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="order" value="0"/>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="1"/>
</bean>

To make it more clear what I am trying to do, I need to be able to have view states like this:

<view-state id="someState" view="/someDir/foo"><!--render foo.jsp -->
    <transition on="foo" to="bar"/>
</view-state>

<view-state id="someState" view="something.core"><!--render tile defintion named 'something.core' -->
    <transition on="foo" to="bar"/>
</view-state>

Does anyone know how to configure things so that I can get it to render tiles definitions and plain jsps?


Answer:

As you say, you cannot chain these together. The javadoc for both states clearly that they must both be at the end of the resolver chain.

I suggest that if you really need to use these togather, then you write a simple custom implementation of ViewResolver which takes the view name, and decides which of your two "real" view resolvers to delegate to. This assumes that you can tell which resolver to call based on the view name.


So you'd define a custom ViewResolver like this:

public class MyViewResolver implements ViewResolver {

    private ViewResolver tilesResolver;
    private ViewResolver jspResolver;

    public void setJspResolver(ViewResolver jspResolver) {
        this.jspResolver = jspResolver;
    }

    public void setTilesResolver(ViewResolver tilesResolver) {
        this.tilesResolver = tilesResolver;
    }

    public View resolveViewName(String viewName, Locale locale) throws Exception {
        if (isTilesView(viewName)) {
            return tilesResolver.resolveViewName(viewName, locale);
        } else {
            return jspResolver.resolveViewName(viewName, locale);
        }
    }

    private boolean isTilesView(String viewName) {
    .....
    }
}

You'd need to implement the isTilesView method to decide which resolver to delegate to.

In the XML config, define this new view resolver, and make sure it appears before the other ones.

<bean class="MyViewResolver">
    <property name="tilesResolver" ref="tilesViewResolver"/>
    <property name="jspResolver" ref="viewResolver"/>
</bean>

Question:

I am using Spring WebFlow 2 and I want to know the diff of decision-state vs action-state.

I am reading up and dont understand the diff of decision-state vs action-state. I understand that view-state will display a jsp for input but whats the diff of decision-state vs action-state?

why should I use decision-state over a action-state? why should I use a action-state over a decision-state?

Can someone shot some light on this


Answer:

Generally, decision-state is used exclusively for a boolean conditional. It's more clear and concise as to what it occurs.

For instance,

<decision-state id="myDecisionState">
    <if test="myBooleanFunction()" then="resultIsTrueState" else="resultIsFalseState" />
</decision-state>

This can be replicated using an action-state like so:

<action-state id="myActionState">
    <evaluate expression="myBooleanFunction()" />
    <transition on="yes" to="resultIsTrueState" />
    <transition on="no" to="resultIsFalseState" />
</action-state>

However, the difference is that action-state does not just operate on booleans - it can trigger transitions on String (string value), Boolean (yes/no), Enum (enum name) with any other result considered a success.

So, by contrast to a decision-state which actually has to decide something, an action-state can simply be used to execute some code.

<action-state id="myActionState">
    <evaluate expression="myFunction()" />
    <transition on="success" to="myNextState" />
</action-state>

I hope that clears stuff up.

Question:

We are using Spring Web Flow (2.0.9) in the Weblogic 10 clustured environment. And in production we are getting a lot of LockTimeoutException : Unable to acquire conversation lock after 30 seconds.

I have been trying to figure out why does above exception comes in some cases when there is only a single click or we are accessing the home page of the site itself.

Please find the code which is trying to lock for FlowController in SWF. What I can't figure out is the lock is on the servlet which is being accessed or something else ?

Please help to understand in a web application when this lock occurs which resource is actually locked in SWF ?

To understand the concept of ReentrantLock , please refer to the link below.

What is the Re-entrant lock and concept in general?

Thanks in advance.

Exception Stack Trace

org.springframework.webflow.conversation.impl.LockTimeoutException: Unable to acquire conversation lock after 30 seconds
    at org.springframework.webflow.conversation.impl.JdkConcurrentConversationLock.lock(JdkConcurrentConversationLock.java:44)
    at org.springframework.webflow.conversation.impl.ContainedConversation.lock(ContainedConversation.java:69)
    at org.springframework.webflow.execution.repository.support.ConversationBackedFlowExecutionLock.lock(ConversationBackedFlowExecutionLock.java:51)
    at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:166)
    at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
    at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.java:174)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)

Lock Implementation in SWF

package org.springframework.webflow.conversation.impl;

import java.io.Serializable;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A conversation lock that relies on a {@link ReentrantLock} within Java 5's <code>util.concurrent.locks</code>
 * package.
 * 
 * @author Keith Donald
 */
class JdkConcurrentConversationLock implements ConversationLock, Serializable {

    /**
     * The lock.
     */
    private ReentrantLock lock = new ReentrantLock();

    public void lock() {
        // ensure non-reentrant behaviour
        if (!lock.isHeldByCurrentThread()) {
            lock.lock();
        }
    }

    public void unlock() {
        // ensure non-reentrant behaviour
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

Answer:

Spring Webflow operates as a state-machine, executing transitions between different states which might have associated views. It doesn't make sense to have multiple concurrently executing transitions, so SWF uses a locking system to make sure that each flow execution (or conversation) only handles one HTTP request at a time.

Don't get too hung up on the concept of ReentrantLock, it just prevents the same thread waiting on a lock that it already holds.

In answer to your question, it is only the flow execution (the specific conversation instance) that is locked by Spring Webflow for the duration of the request handling. The server will still handle requests from other users, or even requests from the same user to a different flow execution.

LockTimeoutException is tricky to troubleshoot because the root problem is not the thread throwing the exception. The LockTimeoutException occurs because another earlier request is taking longer than 30 seconds, so it would be a good idea to find out why the earlier request took so long.

Troubleshooting ideas:

  • Implement a FlowExecutionListener which measures how long each request takes, and log long requests along with the flowId, stateId and transition event, this will allow you to hone in on long-running requests.
  • One good way to avoid the LockTimeoutException itself is to disable submit buttons & links using javascript once a button/link has been clicked. Obviously this doesn't solve the problem of the initial 30-second+ request.

You could increase the timeout for LockTimeoutException, but that doesn't solve the actual problem and leads to a worse user-experience. 30-second requests are the problem.

Finally, you mentioned:

I have been trying to figure out why does above exception comes in some cases when there is only a single click or we are accessing the home page of the site itself.

I suggest that you try re-create the problem with the browser's developer tools window open, watching the 'Network' tab, maybe there is an AJAX request running in the background which is holding the lock.

Question:

When I create a model I would like to save images for a model. I am using PrimeFaces fileUpload component. When I save pictures I want to know to which model particular image refers to. That's why I need to send id of a model to backing bean.

Is there any possibility to send id of model to fileUploadListener?

<h:form enctype="multipart/form-data">
  <p:panelGrid columns="2">
    <h:outputLabel for="hotelName" value="#{msg.hotelName}"/>
    <p:inputText value="#{apartmentNew.name}" id="hotelName"/>
    <h:outputLabel for="hotelDescription" value="#{msg.hotelDescription}"/>
    <p:inputText value="#{apartmentNew.description}" id="hotelDescription"/>
    <h:outputLabel for="hotelImages" value="#{msg.hotelImages}"/>
    <h:form enctype="multipart/form-data">
      <p:fileUpload id="hotelImages"
                    fileUploadListener="#{apartments.handleImageUpload}"
                    mode="advanced"
                    sizeLimit="10000000"
                    allowTypes="/(\.|\/)(gif|jpe?g|png)$/">
      </p:fileUpload>
    </h:form>
  </p:panelGrid>
  <p:commandButton id="saveApartmentButton" value="#{msg.save}" action="save"/>
  <p:commandButton id="cancelCreationApartmentButton" value="#{msg.cancel}" 
     action="cancel"/>
</h:form>

Answer:

Not via request parameters. You can do so via component attributes.

E.g.

<p:fileUpload ...>
    <f:attribute name="foo" value="bar" />
</p:fileUpload>

with

String foo = (String) event.getComponent().getAttributes().get("foo"); // bar

Question:

I've different view-state's in flow.xml. All of theses states have the same view. Now i want to set a variable which includes just a String und call it in the view-file to customize the content. Here are my files: flow.xml: for the example two of the view-state's

<view-state id="rcpm" view="rc/rcmembers.xhtml">
    <on-entry>
        <evaluate expression="RCHtmlCache.getCommunityList('rcpm')"
            result="flowScope.members" />
    </on-entry>
</view-state>

<view-state id="rcarch" view="rc/rcmembers.xhtml">
   <on-entry>
        <evaluate expression="RCHtmlCache.getCommunityList('rcarch')"
            result="flowScope.members" />
    </on-entry>
</view-state>

In this file i need a variable with the value of the view-state ID, so e.g "rcarch".

rcmembers.xhtml just the part of the code where i want to call the variable

<p:panel id="panel" header="Memberslist of **Here comes the value of the variable">

Hope you understand my problem...


Answer:

You have two options:

First, you can define it at flow definition level and expose it to the view directly:

<on-entry>
   <set name="flowScope.myView" value="flowRequestContext.currentState.id"/>
</on-entry>

Or you could pass the flow context to the controller and then expose it there:

<evaluate expression="RCHtmlCache.getCommunityList(flowRequestContext)" result="flowScope.members"/>

On the controller:

public String getCommunityList(RequestContext context) {
   context.getFlowScope().put("myView", context.getCurrentState().getId());
   ...
}

Hope that helps

Question:

I have an action-state that evaluates an expression and then transitions to various other states depending on the result. One of the result states is a subflow-state that hands control to another flow, example;

<action-state id="doWork">
    <evaluate expression="someAction.doWork(someInput)" />
 <transition on="WORKSUCCESS" to="workSuccess" />
 <transition on="WORKFAIL" to="fixFail" />
</action-state>

<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
    <input name="someNumber" value="1" type="java.lang.Integer" />
    <transition on="finish" to="workSuccess" />
</subflow-state>

As you can see I can pass an input into the subflow via the input tag but my question is how can I specify and pass additional inputs that I want present if and only if the subflow-state is being called from the transition WORKFAIL? Assume the subflow-state "fixFail" can be called from other action-states.

I've tried things similar to the following with no effect;

<action-state id="doWork">
    <evaluate expression="someAction.doWork(someInput)" />
 <transition on="WORKSUCCESS" to="workSuccess" />
 <transition on="WORKFAIL" to="fixFail">
            <attribute name="newInput" value="3000" type="java.lang.Integer" />
    </transition>
</action-state>

<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
    <input name="someNumber" value="1" type="java.lang.Integer" />
    <input name="someNumber2" value="flowScope.newInput" type="java.lang.Integer" />
    <transition on="finish" to="workSuccess" />
</subflow-state>

Answer:

There are three ways you can do this. You can do it through the conversation, session or as attributes passed in.

  • ConversationScope: If a field is in the conversationScope the field is visible anywhere in that specific flow as well as that flow's subflows (and their transitions)

  • SessionScope: (Probably not what you want) Is visible to all flows and their subflows

Finally you can pass the field as an attribute into the subflow state for example

<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
    <input name="someNumber" value="1" type="java.lang.Integer" />
    <input name="someNumber2" value="flowScope.newInput" type="java.lang.Integer" />
    <transition on="finish" to="workSuccess" />
</subflow-state>

In your subflow's xml

<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <input name="someNumber"/>
    <input name="someNumber2"/>
    ...
</flow>

In this example someNumber and someNumber two are passed in as attributes to your subflow. In which you can evaluate them as ${someNumber}

Edit:

This is to address your comment question. If you wanted to set a variable in the conversation scope on a specific transition you can do:

<transition on="WORKFAIL" to="fixFail" >
  <set name="conversationScope.someVariable" value="Hello World"/>
</transition>

Then in your jsp

${someVariable}  <!-- This will print out 'Hello World' -->

Question:

The spring webflow documentation mentions that their way of adding messages to a flow is to define all messages regarding that flow in a file messages.properties inside the flow:

Internationalized messages are defined in message bundles accessed by a Spring MessageSource. To create a flow-specific message bundle, simply define messages.properties file(s) in your flow's directory. Create a default messages.properties file and a .properties file for each additional Locale you need to support.

In our webapp we use a mix of Spring Webflow and proprietary frameworks. We have all our internationalized messages in a single file and we'd like to have Spring Webflow access this one instead of littering our project with dozens of properties files. Is there a way to configure the message source for a spring webflow or are we stuck to messages.properties?


Answer:

Put something like this in your application context XML file:

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename"><value>classpath:yourSharedResourceBundle</value></property>
</bean>

As long as the file is located on the classpath it should be used.

Question:

First, I am using spring webflow and some spring javascript to make ajax calls easier.

As of right now, I am having ajax make a call into webflow to display the appropriate fragment.

So I am attempting to use Spring.AjaxEventDecoration for my ajax needs for my application. However, I am having some trouble with this method and webflow and from what I can tell, there are very few examples available to work with.

On a side note, I am not using a form or a select box. I thought I would mention this since every example I've found has used a form/form submit with onlick event or select box with onchange event.

Main question: if I have a method in my webflow that has parameters coming from my ajax, can I actually pass in the parameters from ajax to webflow?

Code:

<transition on="disassociateProperty" >
     <evaluate expression="dService.disassociateProperty(requestParameters.currentPId ,currentD)"  result="flowScope.currentD" />
<render fragments="PList" />
</transition>

So, when I look at the ajax call in firebug, it has the parameter I'm passing in (currentPId) and the correct eventId.

I put a debug point on the first line of the disassociateProperty method and it tells me currentPId is null.

So I would assume requestParameters.currentPId in webflow isn't pulling the currentPId from the ajax call.

Is this expected? Could anyone explain and give an example?

I would appreciate any help provided.

Adam


Answer:

If you think that the problem comes from ajax call, it would be helpful if you write here the ajax call, so we could check if the call is being done correctly.

You could try to pass the form serialized in the data parameter when doing the ajax call. Also, do not forget to add the ajaxSource parameter in the URL. Hope this help.

HTML example:

<form id="formId" method="post" action="${flowExecutionUrl}&_eventId=disassociateProperty">
    <input type="text" id="currentPId" />
</form>

jQuery Example:

$.ajax({
        type: "POST",
        data: $("#formId").serialize(),
        url: $("#formId").attr("action") + "&ajaxSource=true",
        ...
});

Question:

My Java web app currently maps certain error codes to an error servlet (spring web flow, actually, but that should be besides the point), by doing this in web.xml:

<error-page>
    <error-code>500</error-code>
    <location>/spring/error?error=500</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/spring/error?error=404</location>
</error-page>

However, in certain cases the server will still crash and give a stack trace dump of some exceptions to the user. (Running on IBM WebSphere btw). My question then is; is it possible to define a fall-back error page that will be used if all other errors don't match? So that we're guaranteed not to end up with a stack trace under any circumstance.


Answer:

Use the following:

<error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/error.jsp</location> 
</error-page>

See http://www.oracle.com/technology/sample_code/tech/java/codesnippet/servlets/HandlingServletExceptions/HandlingServletExceptions.html for more info.

Question:

I have web application, in which I have used Spring framework. For the concurrent session control I have use spring feature where only 1 logged in session will be maintained for 1 user as soon as that user logs in to another session , he/her previous session will be expired.

Now in this case I am getting this message "This session has been expired (possibly due to multiple concurrent logins being attempted as the same user)."

But I get this message on complete white page on browser. I want this message to come on my login screen only.

Here is the part of my spring security xml where I have handled concurrent session for user.

<security:session-management invalid-session-url="/login.jsp?error=sessionExpired" session-authentication-error-url="/login.jsp?error=alreadyLogin">
                    <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false" />
</security:session-management>

Any links specially for customizing this message and redirecting this message on desired web application page will be appreciated.

Thanks in advance.


Answer:

Original XML entry in spring-security.xml

<security:session-management session-authentication-error-url="/login.jsp?error=alreadyLogin">
                    <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false" />
</security:session-management>

Just You have to added following parameter in xml to redirect the Login expired action or invalid session url

expired-url="url value"

invalid-session-url="url value"

Modified XML entry

<security:session-management invalid-session-url="/login.jsp?error=sessionExpired" session-authentication-error-url="/login.jsp?error=alreadyLogin">
                    <security:concurrency-control max-sessions="1" expired-url="/login.jsp?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false" />
</security:session-management>

Question:

Apache Tiles 2.1.3 has a wildcard feature where a tiles definition includes an asterisk:

<definition name="flow/*" extends=".mainTemplate">
    <put-attribute name="header" value="/WEB-INF/jsp/header.jsp"  />
    <put-attribute name="body" value="/WEB-INF/jsp/flow/{1}.jsp"  />
</definition>

It's explained here, but basically this layout is used for any JSP in the "flow" directory.

The problem is Spring Webflow produced infinite recursion with Tiles:

org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'createAccount' of flow 'jsp/flow'
Caused by: java.lang.IllegalStateException: Exception occurred rendering view null
Caused by: java.lang.NullPointerException

I wound up inserting many individual Tiles definitions instead of one wildcarded definition (insert frowny face here).

How does Tiles wildcards work with Spring WebFlow?


Answer:

Simple fix: You cannot use the default Web Flow view names with wildcarding because you cannot create a wildcard Tiles definition like this:

<definition name="*" extends=".flowTemplate">
    <put-attribute name="header" value="/WEB-INF/jsp/header.jsp"  />
    <put-attribute name="body" value="/WEB-INF/jsp/flow/{1}.jsp"  />
</definition>

The Tiles system goes into a (seemingly) infinite loop if you provide a pure "*" definition like this:

name="*" 

The way to do this is to provide a definition like this:

<definition name="flow/*" extends=".flowTemplate">
    <put-attribute name="header" value="/WEB-INF/jsp/header.jsp"  />
    <put-attribute name="body" value="/WEB-INF/jsp/flow/{1}.jsp"  />
</definition>

And then force your Web Flow view names to that form, like so:

<view-state id="myView" model="myView" view="flow/myView">
    <transition on="back" to="previousView" />
    <transition on="next" to="nextView" />
</view-state>

The default view name is the view id, in this case "myView". You can't give your view an id of "flow/myView" but you can specify the view name separately with

view="flow/myView"

and that will feed the correct value to the Tiles resolver. I'm sure that there are additional wrinkles to Tiles view naming and Web Flow view resolution, but this solved my problem.

Be sure to reference the correct URL (i.e., inject "flow/" as appropriate).