众所周知,可以通过某些URL直接从浏览器或某些外部应用程序调用有限任务流。 如果任务流的属性“ URL invoke”设置为“ url-invoke-allowed”,则启用此功能,该功能通常在集成项目中使用。 通常,客户端(或调用者)使用HTTP GET方法并在URL中传递其参数。 让我们考虑一个带有一个必需输入参数的简单任务流:
<task-flow-definition id="task-flow-definition"> <input-parameter-definition id="__23"><name id="__24">userName</name><value id="__67">#{requestScope.userName}</value><class id="__63">java.lang.String</class><required/></input-parameter-definition> ...
可以通过这样的URL调用任务流
http://127.0.0.1:7101/TestApp/faces/adf.task-flow?adf.tfId=task-flow-definition&adf.tfDoc=/WEB-INF/task-flow-definition.xml&userName=xammer
客户端使用简单的html表单构造此GET请求:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body><form action="http://127.0.0.1:7101/TestApp/faces/adf.task-flow"><input type="hidden" name="adf.tfId" value="task-flow-definition"/> <input type="hidden" name="adf.tfDoc" value="/WEB-INF/task-flow-definition.xml"/> <label> User Name <input type="text" name="userName" value="xammer"/> </label><input type="submit" value="Submit"/></form></body>
</html>
它看起来像这样:
一些客户端更喜欢使用HTTP POST方法,这是他们的要求:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body><form action="http://127.0.0.1:7101/TestApp/faces/adf.task-flow" method="POST"><input type="hidden" name="adf.tfId" value="task-flow-definition"/> <input type="hidden" name="adf.tfDoc" value="/WEB-INF/task-flow-definition.xml"/> <label> User Name <input type="text" name="userName" value="xammer"/> </label><input type="submit" value="Submit"/></form></body>
</html>
而且效果很好。 在这种情况下,URL将如下所示:
http://127.0.0.1:7101/TestApp/faces/adf.task-flow
所有其他必要的信息(例如任务流ID和参数值)都在POST请求中。 但是问题在于,它仅对R1有效。 如果我们在R2上进行尝试,将会得到以下结果:
ADF_FACES-30179:有关更多信息,请参见服务器的错误日志中以下列开头的条目:UIViewRoot为空。 PhaseId期间的致命异常:RESTORE_VIEW 1。
为什么? 因此:
oracle.adfinternal.controller.application.InvokeTaskFlowException: ADFC-02006: A task flow ID is not found in the URL.at oracle.adfinternal.controller.util.UrlParams.getTaskFlowInfo(UrlParams.java:144)at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.
invokeTaskFlowByUrl(RemoteTaskFlowCallRequestHandler.java:84)at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.
doCreateView(RemoteTaskFlowCallRequestHandler.java:63)
本应在POST请求中传递的所有必需数据(包括任务流ID)都将丢失。 为什么? 因为“回送”。 如果在单击“提交”按钮后发现从浏览器发送到服务器的请求,我们将看到以下内容:
因此,服务器不发送“诚实”响应,而是发送一些“回送”脚本,该脚本生成“窗口ID”,并发送具有生成的窗口ID的以下GET请求。 凉! 但是所有发布数据都消失了。 GET请求绝对为空。
幸运的是,如果初始POST请求已经具有一些“窗口ID”,则该框架不会生成任何“环回”。 因此,本例的解决方法是开发一个servlet过滤器,为我们的请求设置“ window id”属性:
public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain)throws IOException, ServletException
{HttpServletRequest r = (HttpServletRequest) servletRequest;HttpSession s = r.getSession();//May be this is not an initial request and window id has been generated earlier//We want all the following requests to work with the same window id //For our use-case this is ok String windowID = (String) s.getAttribute(_WINDOW_ID_KEY);if (windowID == null){String pathInfo = r.getPathInfo();//This is an initial POST request to get access to the task flowif (("/adf.task-flow").equals(pathInfo) &&"POST".equals(r.getMethod())){windowID = WINDOW_ID;//Save window id in the session s.setAttribute(_WINDOW_ID_KEY, windowID);}}//Setup attribute for the request//This will prevent generating of the loopbackif (windowID != null)r.setAttribute(_WINDOW_ID_KEY, windowID);filterChain.doFilter(servletRequest, servletResponse);
}private static final String __WINDOW_MANAGER_KEY = RichWindowManager.class.getName();
private static final String _WINDOW_ID_KEY = __WINDOW_MANAGER_KEY + "#WINDOW_ID";
private static final String WINDOW_ID = "wextflow";
请注意,此过滤器应位于过滤器链中的“特立尼达”过滤器之前:
<filter><filter-name>ExtPostFilter</filter-name><filter-class>com.cs.fusion.core.view.filter.ExtPostFilter</filter-class></filter> <filter><filter-name>trinidad</filter-name><filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class></filter><filter><filter-name>ServletADFFilter</filter-name><filter-class>oracle.adf.share.http.ServletADFFilter</filter-class></filter>
而已!
翻译自: https://www.javacodegeeks.com/2013/08/adf-url-task-flow-call-with-http-post-method.html