Wednesday, May 23, 2007

J2EE Container Managed Security: How to reference the current user


When J2EE container managed security is used the User Principal can be referenced in a number of ways:


Expression Language
       <af:outputText value="#{facesContext.externalContext.userPrincipal.name}"/>

Managed / Backing Bean
       ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
String userName = ectx.getUserPrincipal().getName();
System.out.println("Current user: " + userName);

ADF BC Application Module
       String userName = getUserPrincipalName();
System.out.println("Current user: " + userName);


Tuesday, March 27, 2007

Programmatically removing all entities from a view object

Recently I had a case where I needed to remove all rows from a view object and found that there was no existing method to do this.
The case for doing such an action is where there is a Master-Detail relationship and the detail relation is used only of there is a certain condition met in the master. If the condition is met then the detail is required, however if the user changes their mind then we need a way of removing any records that may have been created in the detail.

By adding the following method in the View Object Implementation class we can safely delete all records in the view object:

    public void removeAllRows(){
// rangeSize is -1
Row[] rows = getAllRowsInRange();
for (int r = 0; r < rows.length; r++)
if (rows[r] != null)
rows[r].remove();

}

Saturday, March 24, 2007

How to reduce coding by extending Managed Beans

After coding many backing/managed beans it became clear to me that there were a few things that I seem to be doing over and over, these were:
  • Getting values from the binding layer
  • Setting values in the binding layer
  • Executing operation bindings
  • Using a combination of the above in a backing bean method

The logical thing to do was be to but my code for doing this into a class and extend this class for all of my managed beans. The class is called JSFBean and uses the binding "#{bindings}" to access the binding container. The three methods in the class (so far) are: execute, getValue and setValue.

The bean which I have called JSFBean includes these three methods and some basic error handling. When creating a backing bean simply add "extends JSFBean" to the class definition.

JSFBean.java:
package com.delexian.ui.backing;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.binding.OperationBinding;

public class JSFBean {

public JSFBean() {
}

public DCBindingContainer getBindings() {
FacesContext fc = FacesContext.getCurrentInstance();
ValueBinding vb = fc.getApplication().createValueBinding("#{bindings}");
DCBindingContainer dc = (DCBindingContainer) vb.getValue(fc);

return dc;
}

public boolean execute(String operation){
DCBindingContainer bindings = getBindings();
OperationBinding operationBinding = bindings.getOperationBinding(operation);
if (operationBinding == null){
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage("Invalid Operation", new FacesMessage(operation + " is not a valid operation for this page"));
return true;
}

operationBinding.execute();

return operationBinding.getErrors().isEmpty();
}

public Object getValue(String el){
FacesContext fc = FacesContext.getCurrentInstance();
ValueBinding expr = fc.getApplication().createValueBinding(el);
return expr.getValue(fc);
}

public void setValue(String el, Object value){
FacesContext fc = FacesContext.getCurrentInstance();
ValueBinding expr = fc.getApplication().createValueBinding(el);
expr.setValue(fc, value);

}

}



An example usage in a backing bean Employees.java, extends JSFBean:
package com.delexian.ui.backing;

public class Employees extends JSFBean {
public Employees() {
}

public String calculate_action() {
execute("CalculateCommission");
execute("Commit");
return null;
}
}


Sunday, January 28, 2007

An ADF Faces and XML Publisher Success Story

Deciding on an output mechanism for the application
After months of developing an application using ADF Faces and ADF Business components it came time to solve the last of my integration and design issues: Integrating a reporting/output mechanism. Early in the project I considered the option of using Oracle Reports or doing (redoing) printable versions of the entire entry form. With over 40 sections to the online application form, neither of these options seemed desirable or suitable.

At a recent conference XML Publisher generated quite a lot of interest so I thought I would download it and see what the hype was about. It didn't take long to work out that XML Publisher was going to be the tool of choice for my application. The original Word documents that the application was built from could be used with the data plugged straight in to where it needed to go. One of the big gains was not having to worry about formatting, this alone saved a huge amount of time.

Integrating XML Publisher with JDeveloper
Deepak Vohra has produced an article on OTN called Integrating Oracle XML Publisher with Oracle JDeveloper 10g which provided examples of using the XML Publisher API's in a simple Java Class. To start of with I created a small Java project based on one class which I executed from its Main method. This allowed me to get all the class paths and libraries sorted out and have me a good understanding of the XML Publisher Java API's. I was able to produce and merge PDF documents including page numbering in a very short space of time. I had to set enough memory for the XMP Publisher API's to overcome an out of memory error (Add "-Xmx256m"to your project run properties). The next step was to integrate this into a sandbox J2EE project and start writing to the browser response stream rather than disk. This presented a few challenges immediately, mostly around the location of the Data Template and XSL files which defined the output to be produced. In fact any interaction with the file system would prove to be a problem due to the relative execution changing to the location of the OC4J and not the class that is running. The other key problems were getting a pooled connection to the database and coding any file system operations to run in the embedded OC4J (XP) and target 10.1.3 middle tier (Linux).

Key design problems and their solutions
Getting a pooled connection for use by XML Publisher was solved by exposing a client method from the Application Module which returned a database connection from the connection pool. Getting the connection is described here in Steve Muench's blog.

The next design problem was where to actually call the XML Publisher API's to do all of the processing. The answer in short was a Managed Bean. The bean references the binding layer to get its parameters and is called by a JSP, which sets the response stream for the XML Publisher PDFDocMerger to write its PDF output to.

As for the interaction with the file system, I used a system properties table within the database which contained the various directories for the XML Data Templates and XSL style sheets for the output. I coded an AM method which used System.getProperties().getProperty("os.name"); to work out what OS the OC4J was running under and get the property for that Operating System eg. xmlp.windows.template.dir would get the full path on Windows for the XML Publisher template directory. (not quite write once - run anywhere, but close enough)

Summary
XML Publisher has been a huge win for this particular project and has successfully plugged a huge gap in the output mechanism for the application. The API's are comprehensive and every time looked to see if it could do something, the answer seemed to be yes and more! XML Publisher will definately be my preferred reporting tool for future ADF based projects.