One obvious solution is to create ApplicationModule on the fly and release it at the end of the request, as shown below. This code will work if your entire transaction gets committed within a single request. In other words, this is ideal for those use cases which does not call for maintaining state across requests from the same client.
try{
ApplicationModule applicationModule = Configuration.createRootApplicationModule(qualifiedAMDefName, configName);
//Business logic goes here.......
}catch(Excpetion ex){
//Handle Error
}finally{
Configuration.releaseRootApplicationModule(applicationModule, false);
}Please note that you may need to configure the ServletADFFilter, to ensure the proper initialization of ADFContext while accessing ApplicationModule from a non ADF based servlet (as in the above use case scenario).
This filter reads the configuration from WEB-INF/adf-config.xml and initializes ADFContext. However applications using ADFBindingFilter can skip this filter, as this is already taken care by the binding filter.
What if you need to maintain the conversation state across multiple requests?
This is a bit tricky situation. As you might be updating Entity Objects from separate requests and committing the transaction at the end of the conversation, it's important to pass a session identifier while looking up the ApplicationModule to restore the state. There are set of APIs available which may help you to pass session cookie while creating ApplicationModule. You may need to follow certain system level contracts and APIs to create a 'stateful' ApplicationModule. Needless to say, this approach call for good understanding of the execution path of the binding layer and related APIs to make it working. So let me try explaining yet another interesting approach which may free you from all these hazards.
Using binding layer to access ApplicationModule
Idea is to make use of the binding layer to invoke services(methods) defined at the ApplicationModule. Apparently you may need same set of meta files as used by an ADF Fusion Web application, to automate this process. If you build an ADF Face application, these files are generated by the JDeveloper at the design time. In this specific case, you may need to create them manually(or to avoid the manual error, you may create a dummy project with a page and necessary ApplicationModule method bindings, and copy the generated adfmsrc folder containing the meta files to your Web project).
Now, let us take a step back and see who is responsible for wiring ApplicationModule with view layer in the case of a typical Fusion web application. Fusion applications are configured to use a servlet filter ADFBindingFilter which actually orchestrates the automatic acquisition and release of an
appropriate application module instance based on declarative binding meta-data.
The method
ADFBindingFilter.doFilter() sets up the ADF processing state, and the method ADFBindingFilter.initializeBindingContext() creates an instance of oracle.adf.model.BindingContext by reading the CpxFileName init parameter from the web.xml file. So, next step is configuring this binding filter. You are free to subclass ADFBindingFilter, if you want to customize the run time behavior of this binding guy. Add this to web.xml with proper url-pattern, so that let the run time pick up this filter and execute it before running your page/servlet.<filter>
<filter-name>CustomBindingFilter</filter-name>
<filter-class>web.filter.CustomBindingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CustomBindingFilter</filter-name>
<url-pattern>/adf/*</url-pattern>
</filter-mapping>Servlet code that access ApplicationModule may look like as shown below
BindingContext bindingContext=null;
try {
bindingContext = BindingContext.getCurrent();
DCBindingContainer dcBindingContainer =
bindingContext.findBindingContainer("view_dummyPageDef");
JUCtrlRangeBinding depts =
(JUCtrlRangeBinding)dcBindingContainer.findCtrlBinding("DepartmentsView1");
dcBindingContainer.refreshControl();
// Business logic goes here...
}finally {
// Clean up goes here...
}Now you can try running your servlet. Please make sure that servlet URL contains the patterns that you configured for the binding filter. For example, please see '/adf/' appearing in the below URL, which result in interception of the binding filter before invoking the servlet.
http://127.0.0.1:7101/AMWithServlet-UI-context-root/adf/sampleservlet
You can download the sample workspace from here. Unzip the project and run the SampleServlet.java
[Runs with Oracle JDeveloper 11g R1 PS1 + HR Schema]
This article inspired by an example from Steve Muench
