Pages

Showing posts with label JDeveloper 12c. Show all posts
Showing posts with label JDeveloper 12c. Show all posts

The Struggles of Personalization in ADF

A Mike Heeren & Richard Olrichs co-production

ADF comes with the out-of-the-box features of personalization. This means that whenever you configure personalisation, users can persist changes they make to the application across sessions and personalize their experience with the application. We have seen that this feature can also confuse some of our users, so it is not always wise to use this. It depends on the use case you have. However, when recently implementing personalization on an ADF 12.2.1.2 application, we had a couple of issues regarding persisting these personalizations to the MDS.

We felt that most of the blogs we came across while implementing these features, share the joyful out-of-the-box configuration. Just select some of the checkboxes in the properties and you are done, ready to enjoy your beer and have your designers and product owners cheer for you.
Sometimes however, real life applications at customers do not match the out-of-the-box configuration and things can become a little bit more tricky than you might expect.

Let's start at the top, and go through some of the steps you will always need within your application for personalization to work. You need to have authentication and authorization set up. If you also want to follow our struggles, we have posted a sample application at the end of this blog to show both the problems as well as the solutions.

Getting started with customizations

The basic configuration of customization in ADF is pretty simple. We start with a simple ADF application (with authentication already configured), and select the Project Properties > ADF View. Here we check Enable user customization and Across sessions using MDS, as seen below:



When enabling user customizations, the following files are edited:
In the adf-config.xml file the following lines are added:

 
  oracle.adf.view.rich.change.MDSDocumentChangeManager
 


In the web.xml file the javax.faces.FACELETS_RESOURCE_RESOLVER context-param is changed from oracle.adfinternal.view.faces.facelets.rich.AdfFaceletsResourceResolver to oracle.adfinternal.view.faces.facelets.rich.MDSFaceletsResourceResolver, and the following blocks are added:

 adflibResources
 oracle.adf.library.webapp.ResourceServlet

...

 adflibResources
 /adflib/*

...

 ADFLibraryFilter
 oracle.adf.library.webapp.LibraryFilter

...

 ADFLibraryFilter
 /*
 FORWARD
 REQUEST

...

 oracle.adf.jsp.provider.0
 oracle.mds.jsp.MDSJSPProviderHelper


 org.apache.myfaces.trinidad.CHANGE_PERSISTENCE
 oracle.adf.view.rich.change.FilteredPersistenceChangeManager


Finally, the following block will be added to the project .jpr file:

 
 


After this we need to configure the adf-config.xml file and add the oracle.adf.share.config.UserCC Customization Class on the MDS tab. This is a default customization class that is shipped with ADF. You can also write your own, but that is more of a use case for customization than it is for personalization. In our case we’ll just configure the application using the UserCC:



Now you need to configure the components that you want the end user to be able to personalize. This can be done in the View tab. Select the ADF Faces Components Tag Library, because we want to personalize the table and column components, these are default component from ADF Faces. By default all attributes will be persisted, you can uncheck them if you do not wish to persist these:



After the above steps are configured, you can give a fancy demo on your demo application, and everybody is happy. However, in our production application, there were still a few issues to tackle, we struggled with some of these.

Struggle 1: Task flows from libraries combined with a file based MDS on a Windows machine.


Our application was not a simple MVC application, but like many application out there, we used ADF libraries to include taskflows from library projects and included them in a bigger main application. When we turned on personalisation on components from task flows which come from libraries instead of directly from the application, they were not correctly persisted to the file based MDS on Windows machines.

When running the application via JDeveloper (in our example application by right clicking default.jsf in the ViewController project, and selecting Run), we see that the task flow that comes directly from the ViewController project (the table on the left of the screen), behaves as expected. However, when personalizing the table from the task flow that comes from the imported library (so from the ViewControllerLibrary project), we see the following warning in the log files.

    

We can verify that the preferences were persisted to the MDS for the left table, but not for the right table, by opening the application (with the same user) in another browser:



Unfortunately, this issue occurs when using task flows from libraries in combination with using a file based MDS on a Windows machine. Weblogic is not able to create a file path, which contains !/ (which is used to indicate that the resource is part of a library).

Luckily, in our case all other DTAP environments don’t use a file based MDS, but a database MDS. In the database MDS, we don’t have the file path issues, so there we won’t see this issue. So on all environments except the (local) Integrated WLS, we don’t see these warning logs, and we will see both table personalizations being persisted. It might take you some time to realise this, if you do not want to deploy to Dev or Test without having the Personalization working on your local machine.

Struggle 2: Deploying the application as EAR instead of via JDeveloper


Deploying both from JDeveloper as well as creating an EAR file seems to work. However, there was still some struggle there as well. The personalisation was working when deploying via JDeveloper, but when we would build in EAR from the application via JDeveloper, and deploy it manually to the Integrated WLS via the console, none of the settings were persisted to the MDS, and we saw the following warning in the log files:

     

By opening the application in different browsers again, we can also confirm that neither of customizations the tables is persisted in the MDS now:



When Personalization across sessions with the MDS is configured, JDeveloper always creates a metadata store usages in the adf-config file at deployment time. This configuration is named MAR_TargetRepos.

It does not matter that we have configured a different metadata store usages within the adf-config. If the MAR_TargetRepos is not present while creating the EAR file, it will be added to the adf-config file. The only solution that we found to this, is by naming our metadata store usages to match the expected default, then it will not override or add anything.


      
            
      
 
  
   
    
    
   
  
 


Note that we did not set deploy-target to true, because if we do this, our custom MAR_TargetRepos will be overridden with the default implementation again, when building the EAR file. This default implementation does not contain the FileMetadataStore implementation:



Because we want to override the default MAR_TargetRepos, so the personalization will also work when deploying the EAR instead of deploying via JDeveloper, we do not set the deploy-target to true so the default (false) will be used. In this case the FileMetadataStore configuration will be preserved in the EAR file.

If we deploy the new EAR file, we see the same behaviour as we did when deploying it via JDeveloper. Also, when we use the personalization functions on the screen, we will see files being created within the PersDef folder within the %TEMP% environment variable.

This FileMetadataStore configuration is changed (back) to a DBMetaDataStore configuration by an ANT build script, before deploying on the different DTAP environments instead of the Integrated WLS environment. An example of such ANT script can be found below.


  
  
  
  
 
  
  
  
  
  
 
 
   
   
 
 
  


Be sure that the WLS_HOME environment variable is set in the system environment variables, and the ear.location property is replaced in the ANT file when you want to use the above example.

Struggle 3: Suddenly our application does persisting during the session.


We have configured the adf-config to persist only certain components and attributes across the session. This works very nice and clear, however, suddenly all the other components also persist their state, just not across the session, but during the session.

It is possible that this is not what you want, it certainly was not what we expected or had in mind for our application, but there is nothing much we can do about it. It would have made more sense to turn this off for all the components and only persist those that were configured to be persisted.

Luckily the ADF components have an attribute persist and dontPersist on them. When reading the documentation on these attributes, it sounds exactly like what we need for our application! Before adding the dontPersist attribute to the hundreds of components we have in the application, we decide to test it on a couple. What we found out was very unpleasing, basically these attributes could be used for documentation purpose or for fun, but it certainly did nothing concerning persistence.

We decided to create our own custom class to adjust the framework and get this working. To achieve this, the context-param org.apache.myfaces.trinidad.CHANGE_PERSISTENCE can be adjusted to a custom class.

At first we tried to extend the oracle.adf.view.rich.change.FilteredPersistenceChangeManager class, which is the class ADF uses by default. However, unfortunately this class is declared final. We decided to create a class that extends the org.apache.myfaces.trinidad.change.SessionChangeManager class, and use the FilteredPersistenceChangeManager as an instance variable. This may not be the prettiest solution, but it serves our purpose:
package nl.whitehorses.personalization.changemanager;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import oracle.adf.view.rich.change.FilteredPersistenceChangeManager;

import org.apache.myfaces.trinidad.change.AttributeComponentChange;
import org.apache.myfaces.trinidad.change.ChangeManager;
import org.apache.myfaces.trinidad.change.ComponentChange;
import org.apache.myfaces.trinidad.change.DocumentChange;
import org.apache.myfaces.trinidad.change.SessionChangeManager;

public class CustomChangeManager extends SessionChangeManager {
 private final FilteredPersistenceChangeManager fpcmInstance = new FilteredPersistenceChangeManager();

 @Override
 public void addComponentChange(final FacesContext context, final UIComponent component, final ComponentChange change) {
     if (component == null || component.getAttributes() == null) {
         return;
     }
     final String[] persistArray = (String[]) component.getAttributes().get("persist");
     if (persistArray == null) {
         return;
     }
     for (final String persistVal : persistArray) {
         if (persistVal != null && change instanceof AttributeComponentChange && ("ALL".equals(persistVal) || ((AttributeComponentChange) change).getAttributeName().equals(persistVal))) {
             fpcmInstance.addComponentChange(context, component, change);
         }
     }     
 }

 @Override
 public void addDocumentChange(final FacesContext context, final UIComponent component, final DocumentChange change) {
     fpcmInstance.addDocumentChange(context, component, change);
 }

 @Override
 public boolean supportsDocumentPersistence(final FacesContext context) {
     return fpcmInstance.supportsDocumentPersistence(context);
 }

 @Override
 public ChangeManager.ChangeOutcome addDocumentChangeWithOutcome(final FacesContext context, final UIComponent component, final DocumentChange change) {
     return fpcmInstance.addDocumentChangeWithOutcome(context, component, change);
 }
}

As you can see, the logic for the persist attribute has been implemented in the addComponentChange method. The addComponentChange method from the FilteredPersistenceChangeManager instance, will only be called when the component contains the persist attribute which is set to ALL. Besides the addComponentChange method, all other (public) methods from the FilteredPersistenceChangeManager have been implemented to use the instance variable as well.
Conclusion

After some struggles and adjustments to the implementation and configuration of the application, we got personalization to work in our real world application used by customers. We overcame the struggles, but this was not as easy as the blogs on the internet made us believe beforehand. We hope that sharing this experience, might save you for some of the troubles we had.

To give you some more insight in the code and the struggles, we have created a (simple) demo application AdfPersonalization, to reproduce the issues we had, and which we used to solve them.

This application consists of the default Model and ViewController projects. Also, we added a ViewControllerLibrary project. This ViewControllerLibrary project is imported as a library by the ViewController project.

The AdfPersonalization application can be deployed to Weblogic in multiple ways:

  • Using the ‘Run’ button in JDeveloper.
  • Using Application > Deploy > … to IntegratedWebLogicServer in JDeveloper. This can be done to verify that struggle 2 is no longer an issue.
  • Using Application > Deploy > … to EAR, followed by running the replace-persdef-repo ANT target from the build.xml file. Afterwards the EAR can be deployed to a Weblogic servers, which is capable using a database based MDS. This can be done to verify struggle 1 is no longer an issue.
  • The source of this project can be downloaded via AdfPersonalization.zip.

Resources




New Release ADF EMG Selenium Tools v3.0.0

First of all, the github repository is now under the ADF EMG repository and not anymore under Wilfred his personal account. On the release page there is a new release of the Selenium Tools, version 3.0.0.

This new version is based on Java 8 (version 52+) and compatible with JDeveloper (and thus ADF) 12.2.1.x. The selenium tools work the same as they always did and the components are still in the com.redheap.selenium.component package, I did not rebrand it all to an org.adfemg package structure because of backwards compatibility.

Resources:



OOW16: What is new in ADF

It was not hard to find the ADF sessions this year at Open World, mainly because there was really only one session. Shay his session about new features in JDeveloper & ADF. It was worth seeing who would show up in the room and to be honest, it was quite crowded for an ADF session. 

JDeveloper 12.2.1.1.0 came out in June 2016, however, this new JDeveloper is only a Patch Set, so mainly bug fixes and not much news compared to last year. Last year I already wrote a blog entry about the JDeveloper 12.2.1.0.0.

ADF Business Components Triggers
These are simple hook points, in both the Entity Object level as wel as the View Object level, just like we know from the database. You can for example create a BeforeDelete trigger or an AfterInsert. 

You can write this in groovy, JDeveloper even has syntax support for that now and will also do a type check on the groovy code.

ADF Remote Regions
The ADF Remote Regions were already in JDeveloper 12.2.1.0.0 as well, however, you might have done a small Proof of Concept and came to the conclusion not to use this. Well, the latest patch set included a lot of bug fixes on the remote regions, so if you ever had a good usecase for this it might be worth reconsidering. 

New DVTs
There are again some new Data Visualisation Tools as well:

Next Release
There was a little bird saying something about 12.2.1.2.0, however, I could not find anything official on this, so we have to sit tight wether we will get an other PatchSet or a release. 

Resources


JDeveloper Shortcut Keys: Reformat All Files in your Project

When writing Java code, it is a good practice to reformat your code before committing it to a source control system. In JDeveloper, you can put this in your save actions, however, JDeveloper will then also reformat all your XML code, this is not always what you want, plus it is a lot slower than reformatting only the Java code.

When in your Java file, you can use the right mouse menu, or the shortcut keys to reformat the java file you are currently working on, this is 'Ctrl' + 'Alt' + 'L' on windows or '⌘' + '⇧' + 'L' on mac.

However, when you change something in your code style, you probably do not want to go by every file individually to reformat the code. Good thing is that JDeveloper can also reformat a whole project at once.
This is not really well documented and it is not in the right mouse window either, but when you select a project in your Application Window and press the shorcut key for reformat, JDeveloper will reformat the whole selected project for you.


JDeveloper Shortcut Keys: Select in Application Window

In more complex projects with a lot of files, you can sometimes lose track of where the files are located. This can be helpful if you have your files saved in a logical package structure. After looking up a file, for example by using the Go to File shortcut key, it might be helpful to know where this file is located.

Well, in JDeveloper there is a shortcut key to find the file in your Application Window. This is 'Alt' + 'Home' on windows or '⌘' + 'Home' on mac. 

As you can see the file is selected and displayed in the Application Window.


JDeveloper Shortcut Keys: Go To File

I have been noticing that a lot of developers are either struggling with finding files in JDeveloper or taking a long time to open all the packages and browsing to the files. However, JDeveloper has a lot of shortcut keys that come in handy.

First of, a shortcut key to 'Go To Java Type', I think most developers know this one. It is the 'ctrl' + '-' on windows or '⌘' + 'J' on mac, you will get this window:

However, did you also know the search is CamelCaseSensitive? It is a very neat trick, imagine you have connected your ADF sources and want to look up the PageFlowScopeMap in the 'org.apache.myfaces.trinidadinternal.context' package.
You can open the 'Go to Java Type' screen and start typing page, but a lot of java classes will come up:

As said the search box understands CamelCase, so if you instead start typing the fist capital of each CamelCase word, in this case 'PFSM' (PageFlowScopeMap) JDeveloper will understand:

How cool is that?

Now this is not where it ends, instead of only searching for Java Types, you can search over all your files in JDeveloper, using the shortcut key: 'ctrl' + 'alt' + '-' on windows or '⌥' + '⌘' + '-' on mac. The following window will popup:

In here you can search for any file, but again you can also search CamelCase, for example, in case I want to search my ViewControllerBundle.properties file:

Now, in both windows you can also use wildcards (*), however the CamelCase will not work in combination with a wild card anymore.


ADF EMG Audit Rules 12.2.1 Released

The ADF EMG Audit Rules are now available on JDeveloper 12.2.1. I want to thanks to Alexis López for reminding me and helping me out!

If you go to Check for Updates, make sure you tick the 'Open Source and Partners Extensions' and click next:

You should see the 'ADF EMG Audit Rules' appear, tick them and click next:

Wait for the download and install, you should see the ADF EMG Audit Rules being installed:

Restart JDeveloper and you are good to go, happy coding!

Combine WC Portal Assets in one Workspace

Working with WebCenter Portal 12c, you can develop your (Shared) Assets within JDeveloper. After installing the WebCenter updates, you can create an WebCenter Portal Asset Application: 

Choose a more generic application name, in my case RichardWcpAssets:

Now in step two I already know I am going to create a Page Template Asset, so I name the Project RichardPageTemplate and accept the default Project Features:

Accept the default package and location in step three and move on to step 4. In here we actually select the Page Template as Asset Type and choose a Display Name, I decided on RichardPageTemplate again and select finish:

Let JDeveloper generate the files for you, now, next to a Page Template, we would also like to define a Skin for our Portal. However, the WebCenter Portal Asset is an Application, so we have to create a totally new Application, just as we did with the Page Template. We do not care about the application name, so you can just let it be a default, like Application2 in my case:

In step 2 we know that this time we want to create a skin, so I named the project RichardSkin and select next:

Leave the defaults again in step 3 and move on to step 4, here we select Skin as Asset Type and change the Display Name to RichardSkin as well and click Finish:

Now, we have two different Application, but the good thing is all we are really interested in is inside the project structure. So we close JDeveloper and we navigate to the location of the applications on our file system. We can take the RichardSkin project folder and move it into the RichardWcpAssets application folder:

After this there is no use for the temporary Application2 anymore, so we can delete this. Now restart JDeveloper and navigate back to the initial Application, in my case ‘RichardPageTemplate’. Open the application menu and choose Open Project:

Navigate to the Skin project you just moved to the Asset application, select the .jpr file and open it:

Save your changes and you can now edit both your Page Template and your Skin from within the same JDeveloper Application.

Read more about Assets development in the following resources:

OOW15: New features in ADF 12.2.1

The whole stack of Fusion Middleware 12c  was launched just before open world. This means there is also a new, cooler and better version of Oracle Application Development Framework (ADF) out! It was not too hard to follow all the session about ADF on open world this year, there were not that many to begin with. 

So what is new? To start with, the infrastructure, we can now use JDK 8 in ADF and WebLogic Server version 12.2.1, which is also Java EE7 complaint. It also fully integrates with the Java Cloud Service (JCS) and the Developer Cloud Service (DevCS). JCS supports ADF version 12.1.3 & 11.1.1.7.1 and you can deploy to JCS directly from JDeveloper. The JDeveloper IDE also fully integrates with the GIT repository on the DevCS. You can track and update tasks and issues:

In ADF Business Components (ADF BC) there is now REST support. You can expose your Application Module as a REST service by simply following a wizard. You can also consume REST services by using the REST Data Control in JDeveloper, it can consume both REST JSON or REST XML. It has a declarative approach, as you would expect from ADF and security supports for OWSM policies.

On the view side, the Alta UI is now enabled by default, there is also a browser based theme editor application. You have a visually modification of the look and feel, create ADF skins and import the jar this application create in your application to use the skin in your ADF application. Next to the skinning, there are more, better and newer Data Visualization Components (DVTs) as well!

There is a cool new feature that allows you to call Remote Regions, this means that you can call a taskflow that is deployed in another application, possible even on a totally different server. Both the consuming as well as the publishing application need to be made aware of these feature. This means that you can reuse taskflows, without the need of consuming a library in the consuming application. The remote region will be loaded parallel (in the other application). You can pass parameters to the region, just like you are used to.

Last but not least, ADF Faces got a lot better at being responsive! They added the so called ‘Masonry Layout’, this is not a new component, but you create responsiveness by adding predefined style classes to your components. ADF now also supports the media tag, with this you can now change properties on your ADF Faces components based on the media query results.

The order of the assign and transform in the Mediator

In my previous blogpost I pointed out the usage of an assign in a mediator component. This can be useful over the transform in several cases. Besides using one of the two, it is also possible to use them both in the same route. I would not advise using both the assign and the transform to manipulate the same data object, however this is possible.

If you want to do this, it is good to keep in mind in which order the mediator handles the manipulations. I used the same example from the previous blogpost and added an transformation in the mediator.

In the transform, I copy the firstname from the input, to the lastname of the output:
 

Resulting in both a transform and an assign in the mediator:
 

I deployed the service to the Enterprise Manager and will fire the following test:
 

The response already clarifies what happened here, the transform is fired first and only after the transform is done, the assign is being processed, because the input is the same as the output:
 

However, to verify this assumption, we will have a closer look at the flow trace, in the flow trace, we open the instance of the mediator:
 

In here we can clearly see that the xsl transformation is done before the assign.
Keep this in mind when you want to use both the transform as well as the assign option on the same data object in the mediator.


Use the assign instead of a transform in the Mediator

When building less complex services, your BPEL process often uses input and output that is pretty much like the request and response on the wsdl. We would still want to decouple using the mediator component, so there is an extra transformation there which is pretty straight forward.
Sometimes it can be useful, easier and faster to use a assign in the mediator instead of a transform.

Imagine an pretty straight forward xsd:


I created an example BPEL process, also pretty straight forward. The Person is both the input and the output, all the BPEL process does is copy the input to the output and reply it:
 

In the Create Web Service dialog we create a WSDL based on the same XSD, also with a Person as input and output:

As said, because of decoupling, we would still want to have a mediator between the exposed service and our bpel process. We create a mediator and wire it both to the service and to the bpel process.
However, when editing the route, we usually use a transformation to map the input to the output, in this case, we are going to use an assign:

When you click the assign button, this also pop ups and Assign Values dialog, here we can wire the input element to the output element:

This way we use an assign in the mediator instead of creating an xsl transformation for this pretty straight forward transformation.