adf4351使用方法
众所周知,可以通过某些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 flow
if (("/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 loopback
if (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
adf4351使用方法