Page 2 of 2 FirstFirst 12
Results 11 to 13 of 13

Thread: _eventId_ with parameter?

  1. #11

    Default

    yes, that approach would probably work. as you say though not 100% as without javascript the site doesn't function.

    In case people want to improve on my method (please at least vote on the JIRA), I wrap the HttpServletRequest before it even reaches webflow. I guess I should have invested time in doing a patch for webflow...at the time I was sure I was doing something wrong - but turns out I was not.

    Code:
    package com.x.web;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.security.Principal;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    import org.apache.commons.lang.StringUtils;
    import org.apache.commons.lang.text.StrBuilder;
    import org.springframework.web.util.WebUtils;
    
    public class CustomHttpServletRequest implements HttpServletRequest {
    
    	HttpServletRequest request;
    	public CustomHttpServletRequest(HttpServletRequest request) {
    		this.request = request;
    	}
    
    	public Map<String, String[]> getAdditionalParameters() {
    		// only get those related to webflow
    		Map origParams = WebUtils.getParametersStartingWith(request, "_eventIdWithParams_");
    		Map newParams = new HashMap();
    		if (!origParams.isEmpty()) {
    			for (Iterator iterator = origParams.keySet().iterator(); iterator.hasNext();) {
    				String name = (String) iterator.next();
    				// we look for a parameter which includes a url-style query part to it in the input name
    				// this only traps form submissions since they would already be split otherwise
    				// so, see if there are any parameters within an input name
    				String[] split = StringUtils.split(name, '?');
    				if (split.length == 2) {
    					// put the actual eventId transition in - it doesn't care for a value
    					newParams.put("_eventId_" + split[0], new String[] {"dummy"});
    					// split on '&'
    					String[] parameters = StringUtils.split(split[1], '&');
    					// include our extra parameters
    					// NB we pay no attention to array style parameters - its one value per name
    					for (int i = 0; i < parameters.length; i++) {
    						String param = parameters[i];
    						String[] extraParams = StringUtils.split(param, "=");
    						String[] values = new String[]{extraParams[1]};
    						newParams.put(extraParams[0], values);
    					}
    				}
    			}
    		}
    		return newParams;
    	}
    
    	/**/
    	// methods related to getting parameters
    	// TODO we should look at the efficiency of them
    	public String getQueryString() {
    		String query = request.getQueryString();
    
    		StrBuilder queryBuilder = new StrBuilder(query);
    		Map<String, String[]> params = getAdditionalParameters();
    		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
    			String param = (String) iterator.next();
    			String[] values = params.get(param);
    			if (!queryBuilder.isEmpty())
    				queryBuilder.append("&");
    			// we just take the first value and ignore the rest
    			// TODO we should check how a normal request handles this
    			queryBuilder.append(param + "=" + values[0]);
    		}
    		query = queryBuilder.toString();
    		// stick to the api
    		if (StringUtils.isEmpty(query))
    			return null;
    
    		return query;
    	}
    	public String getParameter(String arg0) {
    		String value = request.getParameter(arg0);
    		// it appears this method expects a one off value
    		if (value != null)
    			return value;
    		Map params = getAdditionalParameters();
    		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
    			String name = (String) iterator.next();
    			if (StringUtils.equals(arg0, name))
    				return ((String[]) params.get(name))[0];
    		}
    		return null;
    	}
    	public Map getParameterMap() {
    		Map map = request.getParameterMap();
    		Map params = new HashMap<String, String[]>(map);
    		params.putAll(getAdditionalParameters());
    		return params;
    	}
    	public Enumeration getParameterNames() {
    		Enumeration enumParams = request.getParameterNames();
    		List<String> params = new ArrayList<String>();
    		while (enumParams.hasMoreElements()) {
    			String name = (String) enumParams.nextElement();
    			params.add(name);
    		}
    		params.addAll(getAdditionalParameters().keySet());
    		Enumeration enums = Collections.enumeration(params);
    		return enums;
    	}
    	public String[] getParameterValues(String arg0) {
    		String[] strings = request.getParameterValues(arg0);
    		// we'll transfer to an expandable array, since we may add to it
    		List<String> stringsList = new ArrayList<String>();
    		if (strings != null) {
    			for (int i = 0; i < strings.length; i++) {
    				String str = strings[i];
    				stringsList.add(str);
    			}
    		}
    		Map<String, String[]> params = getAdditionalParameters();
    		for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) {
    			String name = (String) iterator.next();
    			if (StringUtils.equals(arg0, name))
    				for (int i = 0; i < params.get(name).length; i++)
    					stringsList.add(params.get(name)[i]);
    		}
    		if (stringsList.isEmpty())
    			return null;
    		return stringsList.toArray(new String[0]);
    	}
    	/**/
    
    	public Object getAttribute(String arg0) {
    		return request.getAttribute(arg0);
    	}
    	public Enumeration getAttributeNames() {
    		return request.getAttributeNames();
    	}
    	public String getCharacterEncoding() {
    		return request.getCharacterEncoding();
    	}
    	public int getContentLength() {
    		return request.getContentLength();
    	}
    	public String getContentType() {
    		return request.getContentType();
    	}
    	public ServletInputStream getInputStream() throws IOException {
    		return request.getInputStream();
    	}
    	public String getLocalAddr() {
    		return request.getLocalAddr();
    	}
    	public Locale getLocale() {
    		return request.getLocale();
    	}
    	public Enumeration getLocales() {
    		return request.getLocales();
    	}
    	public String getLocalName() {
    		return request.getLocalName();
    	}
    	public int getLocalPort() {
    		return request.getLocalPort();
    	}
    
    
    	public String getProtocol() {
    		return request.getProtocol();
    	}
    	public BufferedReader getReader() throws IOException {
    		return request.getReader();
    	}
    	public String getRealPath(String arg0) {
    		return request.getRealPath(arg0);
    	}
    	public String getRemoteAddr() {
    		return request.getRemoteAddr();
    	}
    	public String getRemoteHost() {
    		return request.getRemoteHost();
    	}
    	public int getRemotePort() {
    		return request.getRemotePort();
    	}
    	public RequestDispatcher getRequestDispatcher(String arg0) {
    		return request.getRequestDispatcher(arg0);
    	}
    	public String getScheme() {
    		return request.getScheme();
    	}
    	public String getServerName() {
    		return request.getServerName();
    	}
    	public int getServerPort() {
    		return request.getServerPort();
    	}
    	public boolean isSecure() {
    		return request.isSecure();
    	}
    	public void removeAttribute(String arg0) {
    		request.removeAttribute(arg0);
    	}
    	public void setAttribute(String arg0, Object arg1) {
    		request.setAttribute(arg0, arg1);
    	}
    	public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
    		request.setCharacterEncoding(arg0);
    	}
    	public String getAuthType() {
    		return request.getAuthType();
    	}
    	public String getContextPath() {
    		return request.getContextPath();
    	}
    	public Cookie[] getCookies() {
    		return request.getCookies();
    	}
    	public long getDateHeader(String arg0) {
    		return request.getDateHeader(arg0);
    	}
    	public String getHeader(String arg0) {
    		return request.getHeader(arg0);
    	}
    	public Enumeration getHeaderNames() {
    		return request.getHeaderNames();
    	}
    	public Enumeration getHeaders(String arg0) {
    		return request.getHeaders(arg0);
    	}
    	public int getIntHeader(String arg0) {
    		return request.getIntHeader(arg0);
    	}
    	public String getMethod() {
    		return request.getMethod();
    	}
    	public String getPathInfo() {
    		return request.getPathInfo();
    	}
    	public String getPathTranslated() {
    		return request.getPathTranslated();
    	}
    	public String getRemoteUser() {
    		return request.getRemoteUser();
    	}
    	public String getRequestedSessionId() {
    		return request.getRequestedSessionId();
    	}
    	public String getRequestURI() {
    		return request.getRequestURI();
    	}
    	public StringBuffer getRequestURL() {
    		return request.getRequestURL();
    	}
    	public String getServletPath() {
    		return request.getServletPath();
    	}
    	public HttpSession getSession() {
    		return request.getSession();
    	}
    	public HttpSession getSession(boolean arg0) {
    		return request.getSession(arg0);
    	}
    	public Principal getUserPrincipal() {
    		return request.getUserPrincipal();
    	}
    	public boolean isRequestedSessionIdFromCookie() {
    		return request.isRequestedSessionIdFromCookie();
    	}
    	public boolean isRequestedSessionIdFromUrl() {
    		return request.isRequestedSessionIdFromUrl();
    	}
    	public boolean isRequestedSessionIdFromURL() {
    		return request.isRequestedSessionIdFromURL();
    	}
    	public boolean isRequestedSessionIdValid() {
    		return request.isRequestedSessionIdValid();
    	}
    	public boolean isUserInRole(String arg0) {
    		return request.isUserInRole(arg0);
    	}
    
    }

  2. #12

    Default

    and we need to override handleRequest in WebFlowController but it has private fields, so we need to replace it:
    Code:
    package com.x.web;
    /*
     * Copyright 2004-2008 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.js.ajax.AjaxHandler;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    import org.springframework.webflow.context.servlet.FlowUrlHandler;
    import org.springframework.webflow.executor.FlowExecutor;
    import org.springframework.webflow.mvc.servlet.AbstractFlowHandler;
    import org.springframework.webflow.mvc.servlet.FlowHandler;
    import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
    
    /**
     * The adapter between the Spring MVC Controller layer and the Spring Web Flow engine. This controller allows Spring Web
     * Flow to run embedded as a Controller within a DispatcherServlet, the key piece of the Spring Web MVC platform. It is
     * expected a DispatcherServlet HandlerMapping will care for mapping all requests for flows to this controller for
     * handling.
     * 
     * @author Keith Donald
     */
    
    // NB we only needed to overwrite handleRequest, but need the whole class since private variables are referenced
    // was org.springframework.webflow.mvc.servlet.FlowController
    
    public class CustomWebFlowController implements Controller, ApplicationContextAware, InitializingBean {
    
    	private FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
    
    	private Map flowHandlers = new HashMap();
    
    	private boolean customFlowHandlerAdapterSet;
    
    	/**
    	 * Creates a new flow controller.
    	 * @see #setFlowExecutor(FlowExecutor)
    	 * @see #setFlowUrlHandler(FlowUrlHandler)
    	 * @see #setAjaxHandler(AjaxHandler)
    	 * @see #setFlowHandlerAdapter(FlowHandlerAdapter)
    	 * @see #afterPropertiesSet()
    	 */
    	public CustomWebFlowController() {
    
    	}
    
    	/**
    	 * Returns the central service for executing flows. Required.
    	 */
    	public FlowExecutor getFlowExecutor() {
    		return flowHandlerAdapter.getFlowExecutor();
    	}
    
    	/**
    	 * Sets the central service for executing flows. Required.
    	 * @param flowExecutor
    	 */
    	public void setFlowExecutor(FlowExecutor flowExecutor) {
    		flowHandlerAdapter.setFlowExecutor(flowExecutor);
    	}
    
    	/**
    	 * Returns the configured flow url handler.
    	 */
    	public FlowUrlHandler getFlowUrlHandler() {
    		return flowHandlerAdapter.getFlowUrlHandler();
    	}
    
    	/**
    	 * Sets the configured flow url handler.
    	 * @param urlHandler the flow url handler.
    	 */
    	public void setFlowUrlHandler(FlowUrlHandler urlHandler) {
    		flowHandlerAdapter.setFlowUrlHandler(urlHandler);
    	}
    
    	/**
    	 * Returns the configured Ajax handler.
    	 */
    	public AjaxHandler getAjaxHandler() {
    		return flowHandlerAdapter.getAjaxHandler();
    	}
    
    	/**
    	 * Sets the configured Ajax handler.
    	 * @param ajaxHandler the ajax handler
    	 */
    	public void setAjaxHandler(AjaxHandler ajaxHandler) {
    		flowHandlerAdapter.setAjaxHandler(ajaxHandler);
    	}
    
    	/**
    	 * Set whether redirects sent by this controller should be compatible with HTTP 1.0 clients.
    	 * <p>
    	 * By default, this will enforce a redirect HTTP status code of 302 by delegating to
    	 * <code>HttpServletResponse.sendRedirect</code>. Setting this to false will send HTTP status code 303, which is
    	 * the correct code for HTTP 1.1 clients, but not understood by HTTP 1.0 clients.
    	 * <p>
    	 * Many HTTP 1.1 clients treat 302 just like 303, not making any difference. However, some clients depend on 303
    	 * when redirecting after a POST request; turn this flag off in such a scenario.
    	 * @see javax.servlet.http.HttpServletResponse#sendRedirect
    	 */
    	public void setRedirectHttp10Compatible(boolean redirectHttp10Compatible) {
    		flowHandlerAdapter.setRedirectHttp10Compatible(redirectHttp10Compatible);
    	}
    
    	/**
    	 * Sets the custom flow handles for managing the access to flows in a custom manner.
    	 * @param flowHandlers the flow handler map
    	 */
    	public void setFlowHandlers(Map flowHandlers) {
    		this.flowHandlers = flowHandlers;
    	}
    
    	/**
    	 * Registers a flow handler this controller should delegate to to customize the control logic associated with
    	 * managing the execution of a specific flow.
    	 * @param flowHandler the handler
    	 */
    	public void registerFlowHandler(FlowHandler flowHandler) {
    		flowHandlers.put(flowHandler.getFlowId(), flowHandler);
    	}
    
    	/**
    	 * Returns the flow handler adapter which this Controller uses internally to carry out handler workflow.
    	 */
    	public FlowHandlerAdapter getFlowHandlerAdapter() {
    		return flowHandlerAdapter;
    	}
    
    	/**
    	 * Sets the flow handler adapter which this Controller uses internally to carry out handler workflow. Call this
    	 * instead of the convenience accesors to completely customize flow controller workflow.
    	 * @param flowHandlerAdapter the flow handler adapter
    	 */
    	public void setFlowHandlerAdapter(FlowHandlerAdapter flowHandlerAdapter) {
    		this.flowHandlerAdapter = flowHandlerAdapter;
    		customFlowHandlerAdapterSet = true;
    	}
    
    	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    		if (!customFlowHandlerAdapterSet) {
    			flowHandlerAdapter.setApplicationContext(applicationContext);
    		}
    	}
    
    	public void afterPropertiesSet() throws Exception {
    		if (!customFlowHandlerAdapterSet) {
    			flowHandlerAdapter.afterPropertiesSet();
    		}
    	}
    
    	// subclassing hooks
    
    	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		// NB wrap the request to manipulate our eventId
    		CustomHttpServletRequest requestWrapper = new CustomHttpServletRequest(request);
    		FlowHandler handler = getFlowHandler(requestWrapper);
    		return flowHandlerAdapter.handle(requestWrapper, response, handler);
    	}
    
    	// internal helpers
    
    	private FlowHandler getFlowHandler(HttpServletRequest request) {
    		FlowUrlHandler urlHandler = flowHandlerAdapter.getFlowUrlHandler();
    		String flowId = urlHandler.getFlowId(request);
    		return getFlowHandler(flowId);
    	}
    
    	private FlowHandler getFlowHandler(String flowId) {
    		FlowHandler handler = (FlowHandler) flowHandlers.get(flowId);
    		if (handler == null) {
    			handler = new DefaultFlowHandler(flowId);
    		}
    		return handler;
    	}
    
    	private static class DefaultFlowHandler extends AbstractFlowHandler {
    		private final String flowId;
    
    		public DefaultFlowHandler(String flowId) {
    			this.flowId = flowId;
    		}
    
    		@Override
    		public String getFlowId() {
    			return flowId;
    		}
    	}
    
    }

  3. #13
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    Quote Originally Posted by afe View Post
    If i understand the problem correct, another way to solve this might be to create hidden fields (dynamically with javascript) when the Button is clicked. And then submit the form.

    Though its not a 100% clean approach, it probably will work just fine.
    Yes, you can do something like this (w/jQuery, for example):

    Code:
    <script type="text/javascript" src="<c:url value="/resources/js/jquery-1.3.2.min.js" />"></script>
    
    ...
    <input id="selection" type="hidden" name="selection" value=""/>
    ...
    
    <%-- In your table, as you iterate through rows... --%>
    <c:forEach var="address" items="${addressList}" varStatus="counter">
       <tr onclick="$('#selection').val('${counter.index}');">
           <td>...</td>
           <td>...</td>
           <%--  action column with edit, delete, etc. buttons --%>
           <td>
               <input type="image" alt="${action_caption}"
                       src="<c:url value="/resources/images/icons/edit.png"/>"
                       name="_eventId_editAddress"/>
               ... other buttons 
           </td>
               
         </tr>
    </c:forEach>
    BTW, the example I gave in the beginning of this thread with setting the value of the image submit control won't work in IE, because the value will be overwritten by the browser. It only works in "good" browsers like Firefox, Safari, etc. So, that is not a viable solution. I am not sure I like Adam's example, just too convoluted, and it is generally a bad idea to create your own "versions" of framework classes vs. overriding or injecting your custom functionality. Definitely, SWF should have built-in support for this in 3.x. Hope they are listening.
    Last edited by constv; Mar 4th, 2010 at 11:13 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •