One of the sessions I am (co-)presenting at Oracle Open World 2009 is on ‘applying the concepts of SOA to and achieving the SOA objectives with User Interfaces’. What goes for SOA and typical programmatic (web)services can be applied to User Interface components to a large extent. Decoupling – cross location, cross technology, cross development team and deployment unit – and reusing based on clear interface definitions and encapsulation of implementation is also available for user interface development.
Our presentation – I am copresenting with my colleague Peter Ebell – introduced the SOA concepts and objectives and demonstrates the application of SOA to the UI, using first Portlets and then ADF Task Flows. Subsequently we introduce WebCenter – as the portlet-infrastructure for ADF and also as the real life example of the notion of reusable, independently developed user interface components. We will discuss the nature of the contract you define for such reusable UI services (parameters, events – inbound and outbound) and demonstrate the steps you have to go through to make it work. Finally we will go into ‘how to add a user interface to a SOA implementation’- or: when does a SOA artefact need a user interface.
You can find the presentation below, embedded from slideshare. You can also download the demo applications we use for this session.
Resources
Download zip file with JDeveloper 11g demo applications for PortletConsumer, Todo TaskFlow and Task Flow Consumer.
WebAppConsumingTaskFlows.zip – the web application consuming the TODO taskflow from the ADF Library.
PortletConsumption.zip – the ADF application that consumes the portlet published by the task flow (application) shown below.
TodoTaskFlowOnly.zip – contains the TODO taskflow that is published both as Portlet and as ADF Library based reusable task flow
Lucas,
Eventhough I could not get a chance to listen you live presentation, your PPT gives an idea of it. Excellent presentation.
What I am wondering is that in your 34th slide, you mentioned that the re-usable taskflow will be deployed as part of consuming application. That means, if there are two applications consuming same taskflow, taskflow will be deployed with both applications.
can’t we deploy the ADF library on weblogic server and refer it in all our applications through weblogic-application.xml via library-ref?
Our test case:
—————-
We have a login flow which I made re-usable using ADF library. I am planning to consume the login taskflow in each of our applications which needs login authentication. I deployed logintaskflow as ADF library and referenced in consuming application.
It did not work. I got the error saying that WEB-INF/loginTaskflow.xml can not be found by ADF controller.
Error Trace:
————-
Error 500–Internal Server Error
oracle.adf.controller.ControllerException: ADFC-06002: unhandled exception
at oracle.adfinternal.controller.util.Utils.createAndLogControllerException(Utils.java:203)
at oracle.adfinternal.controller.engine.ControlFlowEngine.handleException(ControlFlowEngine.java:614)
at oracle.adfinternal.controller.engine.ControlFlowEngine.invokeTaskFlow(ControlFlowEngine.java:212)
at oracle.adfinternal.controller.state.ChildViewPortContextImpl.invokeTaskFlow(ChildViewPortContextImpl.java:102)
at oracle.adfinternal.controller.state.ControllerState.createChildViewPort(ControllerState.java:1312)
at oracle.adfinternal.controller.ControllerContextImpl.createChildViewPort(ControllerContextImpl.java:97)
at oracle.adf.controller.internal.binding.DCTaskFlowBinding.createRegionViewPortContext(DCTaskFlowBinding.java:326)
at oracle.adf.controller.internal.binding.DCTaskFlowBinding.getViewPort(DCTaskFlowBinding.java:281)
at oracle.adf.controller.internal.binding.TaskFlowRegionModel.doProcessBeginRegion(TaskFlowRegionModel.java:129)
at oracle.adf.controller.internal.binding.TaskFlowRegionModel.processBeginRegion(TaskFlowRegionModel.java:90)
at oracle.adf.controller.internal.binding.TaskFlowRegionController.refreshRegion(TaskFlowRegionController.java:116)
at oracle.adf.model.binding.DCBindingContainer.internalRefreshControl(DCBindingContainer.java:3038)
at oracle.adf.model.binding.DCBindingContainer.refresh(DCBindingContainer.java:2759)
at oracle.adf.controller.v2.lifecycle.PageLifecycleImpl.prepareModel(PageLifecycleImpl.java:112)
at oracle.adf.controller.faces.lifecycle.FacesPageLifecycle.prepareModel(FacesPageLifecycle.java:80)
at oracle.adf.controller.v2.lifecycle.Lifecycle$2.execute(Lifecycle.java:137)
at oracle.adfinternal.controller.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:192)
at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener.mav$executePhase(ADFPhaseListener.java:21)
at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener$PhaseInvokerImpl.startPageLifecycle(ADFPhaseListener.java:231)
at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener$1.after(ADFPhaseListener.java:267)
at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener.afterPhase(ADFPhaseListener.java:71)
at oracle.adfinternal.controller.faces.lifecycle.ADFLifecyclePhaseListener.afterPhase(ADFLifecyclePhaseListener.java:53)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:352)
at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:165)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
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 oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:191)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:85)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:420)
at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:54)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:420)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:247)
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:157)
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at oracle.security.jps.wls.JpsWlsFilter$1.run(JpsWlsFilter.java:96)
at java.security.AccessController.doPrivileged(Native Method)
at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:313)
at oracle.security.jps.wls.util.JpsWlsUtil.runJaasMode(JpsWlsUtil.java:146)
at oracle.security.jps.wls.JpsWlsFilter.doFilter(JpsWlsFilter.java:140)
at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:70)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at oracle.adf.library.webapp.LibraryFilter.doFilter(LibraryFilter.java:159)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at oracle.dms.wls.DMSServletFilter.doFilter(DMSServletFilter.java:202)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3588)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2200)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2106)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1428)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Caused by: oracle.adf.controller.ControllerException: ADFC-02001: The ADF Controller cannot find ‘/WEB-INF/loginTaskFlow.xml’.
at oracle.adfinternal.controller.metadata.provider.MdsMetadataResourceProvider.getMetadataObjects(MdsMetadataResourceProvider.java:457)
at oracle.adfinternal.controller.metadata.provider.MdsMetadataResourceProvider.loadUnmutalbeMetadataResources(MdsMetadataResourceProvider.java:367)
at oracle.adfinternal.controller.metadata.provider.MdsMetadataResourceProvider.getResources(MdsMetadataResourceProvider.java:179)
at oracle.adf.controller.internal.metadata.MetadataService.getTaskFlowDefinition(MetadataService.java:216)
at oracle.adfinternal.controller.activity.TaskFlowCallActivityLogic.findTaskFlowDefinition(TaskFlowCallActivityLogic.java:936)
at oracle.adfinternal.controller.activity.TaskFlowCallActivityLogic.invokeTaskFlow(TaskFlowCallActivityLogic.java:185)
at oracle.adfinternal.controller.engine.ControlFlowEngine.invokeTaskFlow(ControlFlowEngine.java:195)
… 58 more
Caused by: oracle.mds.core.MetadataNotFoundException: MDS-00013: no metadata found for metadata object “/WEB-INF/loginTaskFlow.xml”
at oracle.mds.core.MetadataObject.getBaseMOFromCache(MetadataObject.java:1625)
at oracle.mds.core.MetadataObject.getBaseMO(MetadataObject.java:927)
at oracle.mds.core.MDSSession.getBaseMO(MDSSession.java:2627)
at oracle.mds.core.MDSSession.getMetadataObject(MDSSession.java:1144)
at oracle.mds.core.MOResolver.getMetadataObjects(MOResolver.java:201)
at oracle.adfinternal.controller.metadata.provider.MdsMetadataResourceProvider.getMetadataObjects(MdsMetadataResourceProvider.java:411)
… 64 more
Is there a way to make this work?
Thanks in advance.
Thanks & Regards,
Rama Krishna. P
Hi Peter,
Thanks for your comment. We did mention the run-time vs design time integration with Portlets vs. Task Flows in our talk. We discussed Composer and made it clear that in terms of straight decoupling, Portlets definitely have advantages. (then again, many of use may not necessarily have a Portal/Portlet Framework at our disposal) so Task Flows are a nice alternative in many cases – especially with their somewhat richer integration interface.
While we are communicating – I was wondering: in SOA Suite we can implement policies that allow us to handle the unavailability of services – when a call fails, try again or try another service end point or return perhaps an alternative result. I was wondering whether something similar exists for portlets: if the portlet cannot be accessed, could we instruct the WC Framework to try again, try a different provider (endpoint) and when all else fails return with an alternative piece of contents (sort of like the ALT attribute on the HTML IMG element).
anyway, sorry we have not met during this conference – though there is still is some time. best regards,
Lucas
Lucas,
I’m sorry I missed your presentation. Thanks to your hosting the slides I felt like being in the room…
One comment on the comparison of the two component technologies: while I agree that task flows due to their native nature are way simpler and more straight forward in most cases, there’s one major draw back compared to portlets: it’s very hard to add task flows to an already deployed application. The portlet producer registration can be achieved both from Spaces and from a custom WebCenter application at runtime. However, dropping an ADF Library into a deployed app is not straight forward.
Any way – great presentation, thanks for sharing it here.
Peter