Friday, July 9, 2010

If you're seeing StringIndexOutOfBoundsException in org.apache.myfaces.trinidadinternal.style.util.CSSGenerationUtils ...

... then, as explicitly noted on JDeveloper 11g PS2 Release Notes, what you're seeing is a JDK regression bug, namely, 6875866. To workaround it you need to use the -XX:-UseSS42Intrinsics option on two places:

1. Project Properties -> Run/Debug/Profile -> Default (or whatever is your Run Configuration name) -> Edit... -> Java Options -> enter -XX:-UseSSE42Intrinsics in the text box.
2. Edit to your <JDEV_HOME>/jdev/bin/jdev.conf  and add this line:  AddVMOption -XX:-UseSS42Intrinsics

Note that the Release Notes only talk about adding the option to WLS's runtime settings, but you also need it for design time as ADF Faces is being called behind the scenes to render the JSPX files in the IDE. I also recommend to turn on the "Show Design Time Messages in Log" option so you can see any error messages being raised by the JSP/HTML Visual Editor. Go to Preferences -> JSP and HTML Visual Editor panel to turn it on.

Tuesday, April 13, 2010

Using PMD Extension and Custom Rule Sets with JDeveloper 11g

 

Recently I’ve worked with a customer that was evaluating the use of PMD code quality tool integrated with JDeveloper 11g and their custom build process (using Maven/ANT) to improve their code quality and enforce their standards. They were specifically interested in custom ADF Business Components rules.

Although I knew that PMD it provides an extension for JDeveloper 11g I’ve never done any work with PMD before. So I dug into its documentation and found out that you can actually create rules based on both XPath expressions and Java.

Without any previous knowledge of PMD or XPath it took me less than an hour to quickly right some basic XPath rules; and believe me, I’m just your average developer! :^)

I’ve created 5 simple XPath-based rules:

  • Avoid using ViewObjectImpl.getRowCount();
  • Avoid calling transaction methods from ADF BC (commit/rollback/potChanges);
  • Avoid using DBTransaction class;
  • Avoid using direct JDBC calls to the Database;
  • Use of wrong super class for your Application Module.

I won’t go into the PMD implementation details. You can check the excellent PMD documentation for that. And just to make it crystal-clear: I’m not a PMD or XPath expert, so the XPath expression can still be wrong or raise false positives; the objective is just to give an idea of what can quickly be done using PMD and XPath no matter which framework you’re using.

So, here is the step by step process:

1. Fire up JDeveloper, go to Help->Check for Updates and download the PMD Extension. If you cannot find it through the Update Center, download it here and install it.

2. After installing, shutdown JDev. We will need to do some refactoring on the extension jar files due to the way the extension reads the rulesets properties.

3. Open your preferred file browser or command line and go to <JDEV_HOME>\jdeveloper\jdev\extensions\net.sourceforge.pmd.jdeveloper.4.2.5.3.0\lib

4. Open the pmd-4.2.5.jar file with your preferred tool. You’ll see that there is a rulesets directory in it. Extract this directory to your file system and remove the rulesets directory from the jar file. We need to do this to modify the rulesets/rulesets.properties config file that is bundled within the jar file.

5. Open the rulesets.properties file and at the end of the rulesets.filenames append rulesets/adfbc.xml . It should look like this:

rulesets.filenames=rulesets/android.xml,rulesets/basic.xml,rulesets/braces.xml,rulesets/clone.xml,rulesets/codesize.xml,rulesets/controversial.xml,rulesets/coupling.xml,rulesets/design.xml,rulesets/finalizers.xml,rulesets/imports.xml,rulesets/j2ee.xml,rulesets/javabeans.xml,rulesets/junit.xml,rulesets/logging-jakarta-commons.xml,rulesets/logging-java.xml,rulesets/migrating.xml,rulesets/naming.xml,rulesets/optimizations.xml,rulesets/strictexception.xml,rulesets/strings.xml,rulesets/sunsecure.xml,rulesets/unusedcode.xml,rulesets/adfbc.xml




6. Download the adfbc.xml ruleset file to the rulesets folder. Now create a new jar called rulesets.jar with the rulesets directory. You can download the one I’ve prepared from here. Just remember that you still need to remove the original rulesets directory from pmd-4.2.5.jar as explained above.



7. Back on the pmd-4.2.5.jar, open its META-INF/MANIFEST.MF and add a reference to rulesets.jar:



Manifest-Version: 1.0

Ant-Version: Apache Ant 1.7.1


Created-By: 11.2-b01 (Sun Microsystems Inc.)


Main-Class: net.sourceforge.pmd.PMD


Class-Path: jaxen-1.1.1.jar asm-3.1.jar rulesets.jar



What we did was to remove the rulesets dependency from the original jar to an external jar that we can modify at will. Unfortunately the import rules feature of the extension does not work as one would expect.



8. Launch JDev and go to Preferences->PMD. You should see the following rule entries at the bottom of the rules list:



PMDCustomRules



9. I’ve created a Bad Practice ADF BC Project and added some offending code in my ApplicationModuleImpl class to test the rules. If I right click on my AM java source and pick PMD at the bottom of the context menu this is the the output generated:



PMDReport 



Here it is also a call for action: if you want to tackle the task of creating new XPath expressions for ADF, or to improve the existing PMD extension, please get in contact with me. I will try my best to help you.



I won’t go into the details of writing a custom Java-based rule; the documentation at the PMD site is pretty good. The only drawback is that PMD is not able to analyze XML files, which is an essential feature for a good ADF analysis. For that, I will be unleashing the full power of ojaudit and how to write custom audit rules to it. Stay tuned!

Thursday, April 1, 2010

Quick ADF Faces af:table / af:column tip: case insentive QBE

 

Alright, so today I was playing with the out of the box af:table QBE feature, and I noticed that the inputText filters displayed at the top of the table header were case sensitive. I was intrigued and started to debug some internal classes only to be snapped by my fellow colleagues from the ADF Faces team that this is actually a built-in feature of the af:column tag:

   1: <af:column sortProperty="FirstName" filterable="true"



   2:            sortable="true"



   3:            headerText="#{bindings.Employees.hints.FirstName.label}"



   4:            id="resId1c2" width="300"



   5:            filterFeatures="caseInsensitive">




This is correctly documented in the af:column tag documentation.



So, lesson learned: read the fraking doc before annoying your developer friends! >_<

Wednesday, February 24, 2010

Fine grained WebCenter customization using MDS

Recently a customer contacted me asking if it is possible to customize WebCenter Spaces or, more specifically, the Content Presenter Component. The requirement is to, according to some arbitrary condition, show the document title property from UCM instead of its file name – unfortunately the title property is not currently publicly exposed – I’ve create Enhancement Request #9392299 to make the propertyMap property accessible. For now I will show how you can customize a WebCenter library to add the user that last modified the file will to be shown along the file name.

This is a screenshot of the Document Library File Picker window. Only the filename is shown in the file picker dialog:

ContentPresenterFileBrowserFile1

At first one would think that this is way too fine grained to be customized, or you would have to actually modify the source code for the page to add your own customizations and running the risk of breaking the component/application in case it is patched/upgraded – or, file an enhancement request that could take a couple of releases to make its way into the product. But that’s not the case with WebCenter and MDS.

As you probably know already, Oracle ADF and MDS are the foundations for WebCenter, so the same customization that can be applied to your own custom applications can be applied to WebCenter Spaces or any of its components in the same way.

This is what you will need for this exercise:

Create a customization-enabled application

Fire up JDeveloper and create a new WebCenter Application:

WebCenterAppTemplate

Name it accordingly, and give it also a meaningful package name. Go through the rest of the Application wizard steps and finish it.

For this customization we don’t really need a Customization Class. If you want to use a Customization Class I suggest reading the How to Create a Custom SiteCC Tip Layer section of the Developer’s Guide and also check out this cue card.

Let’s enable customization in our application. Go to Application Resources > Descriptors > ADF META-INF :

ContentMDSAppRes

Double click adf-config.xml to open it in overview mode. Now click on the [+] button and type in “SiteCC” (without quotes!). Select the class and click OK:

SiteCC

We also need to enable seeded customizations. For this go to your ViewController project properties, select ADF View and select the Enable seeded customizations checkbox:

VCSeedCust

Next, we register the reserved WebCenter layer on on JDEV_HOME\jdev\CustomizationLayerValues.xml. This is the file that where all layers are registered. If you’re using a Customization Class then remember that the layer value in the class must match the value in this file. The WebCenter layer value is not surprisingly called “webcenter”:

   1: <cust-layers  xmlns="http://xmlns.oracle.com/mds/dt">



   2:   <cust-layer name="site" id-prefix="s">



   3:       <!-- Generated id-prefix would be "s1" and "s2" for values



   4:     "site1" and "site2".-->



   5:       <cust-layer-value value="site1" display-name="Site One" id-prefix="1" />



   6:       <cust-layer-value value="site2" display-name="Site Two" id-prefix="2" />



   7:       <!-- Generated id-prefix would be "s" for value "site"



   8:        since no prefix was specified on the value -->



   9:       <!-- ADF SiteCC always returns the value as "site" -->



  10:       <cust-layer-value value="site" display-name="Site"/>



  11:       <cust-layer-value value="webcenter" display-name="WebCenter"/>



  12:    </cust-layer>




Save the file and close it.



Customizing an ADF Library



Now we need to start JDeveloper in customization mode. Go to Tools > Preferences > Roles and select Customization Developer. JDeveloper will restart automagically. Good time to go grab a coffee or a snack. ;-)



After drinking your coffee and/or having your snack, check if the newly added customization layer has been added successfully. You should be able to see it from the Customization Context Panel. Expand the Value listbox and select the WebCenter option":



CustContext



Go to the Navigator Display Options (yes, there’s a name for that icon) and select Show Libraries:



ShowLibraries



Here I also recommend setting your Package Level and Web Content Level to “Unlimited” so you don’t have to journey into the center of Earth to find what you’re looking for.



Now you should see all the libraries that have been included by default to your ViewController project when it was created.



Hunting for that surreptitious JSPX or JSFF that we need to customize.



Just in case you don’t know the meaning of the word above, here it is. Hey, I’m not a native English speaker and I like to learn new words!



This is where things get really interesting. We now need to find the needle in the haystack. Currently there’s no documentation for the JSPXs/JSFFs inside WebCenter ADF Libraries, and I wouldn’t count for one coming out before the Universe collapses again into a singularity. Due to the sheer amount of files it would be a maintenance nightmare to keep them semantically and syntactically aligned with any external documentation – although I have some ideas myself on how you could do that using RDF (more on that later) . Anyway, that means that we will need to do some investigative work to find out where the file we need to customize is located



Start by locating the ADF Library that most probably has the file. Go to your ViewController project properties > Libraries and Classpath > Add Library and locate the WebCenter Document Library Service View :



AddLibDocLibView



Go back to your ViewController project and locate the library - it was most probably added at the bottom. Now relax, take a deep breath an expand the library node. Look for a package named oracle.webcenter.doclib.view.jsf.fragments . Within it you’ll find the docPickerView.jsff file. That’s our needle!



docPickerView



Now that we found the fragment let’s take a peek at its structure and pinpoint where we need to add our customization. By drilling down into the fragment structure we can see af:panelStrechtLayout (center) > af:switcher > f:facet(tree) > af:tree (nodeStamp) > af:panelGroupLayout > af:outputText :



StructPanePickView



The output text value property, #{item.name}, is the one that renders the filename. Now we need to add a new outputText that will show who last modified the file, but how do you know what properties you can use to populate the outputText value property?



This is the part where things get a bit tricky. There’s no public documentation on what’s being exposed by the item object. After some investigative work I could find that it exposes very few properties like mIMEType, (file)name, lastModifiedBy, lastModified,createDate, and contentType. This is not documented because they are exposed by an internal class called VCRMainViewItemBean. This class also has a boolean isFolder method that we’ll be using to render or not the new outputText we will add to the page. You can find other properties from the jsff page source itself, eg, #{item.icon} returns the icon image for a specific file type.



As I said at the beginning of this post, we don’t have access to the propertyMap object that is exposed by default when you are working with the Content Datacontrol or with Content Presenter. If you want to know more about this just take a look at the chapter Integrating Content of WebCenter Developer’s Guide that explains all the properties that you can use when working with Content Producers in WebCenter, more specifically, this table which lists Oracle UCM properties used by the content adapater.



So let’s add a new outputText. First of all, when you’re on customization mode you’re not able to edit a JSPX/JSFF by editing its source; you have to use the Visual Editor and the Property Inspector for that. From the Component Palette, drag and drop a new outputText just below the existing one:



CustomOutputText



Can you spot what’s strange in the picture above? The Value property is being represented as disabled, but fear not, if you click on the down arrow to the right and bring up the Expression Builder you will be able to change it – not the best usability example, I know. But also notice at the same time how JDev nicely indicates to which layer this customization is being applied. So bring up the Expression builder and enter the following expression:



#{'('}#{item.lastModifiedBy}#{')'}



Literal strings are not supported by MDS, so we need to surround them with EL or, better, use a Text Resource (resource bundle). For this example a Resource bundle is a bit overkill.



ExpressionBuilder



Select the rendered property, bring up the Expression Editor and enter the following expression:



#{!item.folder}



This will guarantee that the outputText won’t be rendered if it is a folder.



It is interesting to see here how the customization is stored by mds. Notice that it uses the same package structure as the basis for the customization, then is adds the mds namespace identifier (mdssys), the customization identifier (cust), the tip layer (site) and the layer value (webcenter).



LibCustomDelta



Then you can see that the xml file that has only the things you customized (the “delta”):





   1: <mds:customization version="11.1.1.55.36"



   2:                    xmlns:mds="http://xmlns.oracle.com/mds">



   3:   <mds:insert parent="dlPkVw" position="last"



   4:               xmlns:f="http://java.sun.com/jsf/core">



   5:     <f:facet xmlns:f="http://java.sun.com/jsf/core" name="bottom"/>



   6:   </mds:insert>



   7:   <mds:insert parent="dldpvpgl6" position="last"



   8:               xmlns:af="http://xmlns.oracle.com/adf/faces/rich">



   9:     <af:outputText xmlns:af="http://xmlns.oracle.com/adf/faces/rich"



  10:                    value="#{'('}#{item.lastModifiedBy}#{')'}" id="sot1"



  11:                    rendered="#{!item.folder}"/>



  12:   </mds:insert>



  13: </mds:customization>






Deploying the customization to MDS



Now that the actual customization is done we need to package it in a Metadata Archive (MAR) for deployment. From the Application Menu, select Application Properties



AppProp



… then select Deployment. Click on the [New…] button and select MAR File from the Archive Type listbox. Enter any meaningful name, eg, customFilePicker. Although it’s not required, I consider a good practice to uncheck all checkboxes in the Deployment panel to avoid any unwanted files in the archive:



DepProf



From the Application Menu, select Deploy > customFilePicker:



DeployCustom



Select the option to generate a jar file; currently you cannot deploy a MAR file from within JDev, so we need to use WSLT tool for that. If your WebCenter Spaces is running in a different machine than transfer the MAR file to it.



On your WebCenter Spaces installation home go to WEBCENTER_ORACLE_HOME/common/bin. In my case,it is /fmw/middleware/Oracle_WC1/common/bin . Now, run the wlst.sh or wlst.cmd script. Now you need to connect to the admin server by using the connect command:



wls:/offline> connect ('weblogic','welcome1','t3://ateam-hq67:7001')

Connecting to t3://ateam-hq67:7001 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'wc_domain'.

Warning: An insecure protocol was used to connect to the
server. To ensure on-the-wire security, the SSL port or
Admin port should be used instead.

wls:/wc_domain/serverConfig>



Where weblogic is the admin user, welcome1 is the password and t3://ateam-hq67:7001 is the admin URL.



Before deploying our customization let’s create a new metadata label - MDS works much like a Version Control System. That way if we mess up the customization we can always revert back by using the promoteMetadataLabel command and avoid headaches. You create a label with the createMetadataLabel command:



wls:/wc_domain/serverConfig> createMetadataLabel('webcenter','WLS_Spaces','preCustomFilePicker');


Executing operation: createMetadataLabel.

Created metadata label "preCustomFilePicker".


Where webcenter is the application name, WLS_Spaces the server name, and preCustomFilePicker the metadata label.



And finally we import the MAR file with the importMetadata command:





   1: wls:/wc_domain/serverConfig> importMetadata(application='webcenter',server='WLS_Spaces',fromLocation='/tmp/customFilePicker.mar')



   2:  



   3: Executing operation: importMetadata.



   4:  



   5: Operation "importMetadata" completed. Summary of "importMetadata" operation is:



   6: List of documents successfully transferred:



   7:  



   8: /oracle/webcenter/doclib/view/jsf/fragments/mdssys/cust/site/webcenter/docPickerView.jsff.xml



   9:  



  10: 1 documents successfully transferred. 




When you enter the fromLocation attribute make sure to use the full file path – you cannot use relative paths.



All these commands have ANT tasks counterparts so you can script the whole process.



The cool part here is that you don’t need to bounce the server to see your new customizations in action!



Using the customized component!


You can test the customization by editing a page on WebCenter Spaces and adding a new Content Presenter document. Put the page in Edit Mode, then click on Add Content and from the Resource Catalog popup select Documents > Content Presenter. Remember that you will need an UCM instance connection configured for that:


ResourceCatalog



From the Content Presenter region, click on the little wrench icon to set up the content to be shown. From the popup, click the Content tab and then the Browse button. The file picker popup will show up with the customization:



CustomFinal



Now our file picker is showing up who has last modified the files stored in UCM.



What you should take from this post is not the exercise per se, but all the things involved when you’re customizing an application and how powerful it is. Hope that you enjoyed and can put it to good use!

Friday, October 23, 2009

Where's the Javadoc for ADF 11g?

If you're using JDev you can have access to the ADF API through different ways. My preferred one is by selecting the class in the source editor and pressing F1 for the full javadoc or Ctrl+D to have the mini-javadoc view (if you have the source code jars) popping up. Another way is to use the global search field on the top right of the IDE.

Sometimes you also want to link the reference to the API from, for example, a blog post. In this case you can access the whole ADF 11g API reference from this link: http://download.oracle.com/docs/cd/E15051_01/apirefs.htm

Wednesday, October 21, 2009

How do I know if I’m inside a Task Flow or not?

If for some esoteric reason you need to know if you're inside a Task Flow or not, here's the snippet for doing so from a backing bean

ViewPortContext ctx = ControllerContext.getInstance().getCurrentViewPort();
TaskFlowId id = ctx.getTaskFlowContext().getTaskFlowId();
if (id != null){
System.out.println("BOUNDED taskflow.");
} else {
System.out.println("UN-BOUNDED taskflow.");
}


ControllerContext is also accessible through EL, so you can use the same logic in our JSF/ADF tags.

OOW09 Unconference Slide Deck Posted

You can now check out the presentation that George and I delivered during Oracle OpenWorld 2009 Unconference session. It talks about some of ADF Faces key components, page layout and how we rebuild two well known websites using ADF Faces.

We will revamping this presentation with more content and more demos for our technical session at Devoxx 2009.