Oracle Forms Modernization site on OTN

25 April 2008 at 13:01 CEST | In Forms, Oracle, Web components | 2 Comments

I just noticed that Grant Ronald, an Oracle Forms product manager, blogged about a new subsite on OTN “Oracle Forms Modernization”

I knew this was coming and I think it’s a good thing. It proves that Oracle is still committed to Oracle Forms as a product. They are helping Oracle Forms customers to get the most out of their investment in showing how Oracle Forms can still be used in the changing technology environment of today. I’m hoping to get my OraFormsFaces solution included on the page as well. It allows you to integrate Forms and JSF/ADF seamlessly which, I think, fits perfectly with the “Forms Modernization” theme.

I just fear the people who keep claiming that Oracle is dropping Forms will use this site as another argument for their cause. They can (will?) argue that Oracle is pushing Forms customers to new technology and that this site is just another means to accomplish this. I guess, there’s nothing Oracle can do to please these people. I think, you should see this site as a positive thing. It’s not telling people to move away from Forms and move to any new technology. It’s just explaining to Forms users how they can integrate Forms with new technology IF they want to (there’s no pressure there). It fits perfectly with the Oracle Forms strategy of “Upgrade and Integrate”; upgrade your Oracle Forms installation to the latest version and benefit from the advantages of new technologies by integrating the two worlds. That happens to fit perfectly with the OraFormsFaces approach as well. It allows you to integrate Forms and JSF seamlessly, in a way that cannot be accomplished with the out-of-the-box Oracle Forms product.

Get JDeveloper 11g technology preview 4

18 April 2008 at 08:08 CEST | In JDeveloper, Oracle, Upgrades and versions | 27 Comments

Watch OTN today. It is rumored that the next technology preview, number 4, will be published today. Don’t really know which timezone though.

It’s been a while since the last technology preview (Christmas 2007), so I’m curious to see how far they’ve come with this next preview. I hope they are getting closer to a finished version. The only official thing Oracle is saying about an official release of Fusion Middleware 11g is calendar year 2008.

Update 25 april 2008: Looks like my information wasn’t 100% correct as the tech preview hasn’t been released on OTN yet. Then let’s just say they’re getting very close and it can be out there any time now.

Using an af:iterator to group and insert breaks

8 April 2008 at 12:35 CEST | In Features and tips, JDeveloper, Oracle | 9 Comments

Yesterday I got a question how to create a ADF Faces JSPX page that shows all the records from a ViewObject, but inserts group headers when one of the fields (category) in the ViewObject changes. In the end, the solution lies in the use of an <af:iterator> component to iterate the rows in the ViewObject and insert breaks where necessary.

The end result looks something like this:

Read the rest of this blog to learn how I achieved this.

First, let me show the output of the SQL statement of the ViewObject:

CODE:
ID TEXT                                     BOOL CATEGORY
-- ---------------------------------------- ---- ---------------------
7  Business Intelligence Enterprise Edition N    Business Intelligence
6  Businesss Intelligence Standard Edition  Y    Business Intelligence
8  Data Integrator                          N    Business Intelligence
1  Database Enterprise Edition              Y    Database Products
2  Database Standard Edition                N    Database Products
3  Oracle Lite                              N    Database Products
4  Application Server Enterprise Edition    N    Fusion Middleware
5  Forms and Reports                        N    Fusion Middleware

I've create a default ADF Business Components Entity Object, View Object, and Application Module. To use a checkbox I need a boolean type attribute, so I added a transient attribute to the View Object:

JAVA:
public Boolean getTrueBool() {
    return "Y".equals(getBool());
}

public void setTrueBool(Boolean value) {
    setBool(value ? "Y" : "N");
}

Next thing to do is to create the ADF Faces JSPX page to iterate over all the rows in the ViewObject and include a checkbox component for each row. Whenever the category of a row changes compared to the previous row a header should be included to indicate the start of a new category. We normally use an af:table component to show multi-record stuff, but you can't use it in this case. It does not allow to output the headers in between the rows. Hence we use the af:iterator component to iterate over the rows of the ViewObject:

XML:
<af:iterator var="row"
             value="#{bindings.TestWilfredViewIterator.allRowsInRange}">

  <af:panelHeader text="Category #{row.category}"
                  rendered="#{CategoriesBean.changed}"/>

  <af:selectBooleanCheckbox text="#{row.text}"
                            value="#{row.trueBool}"/>

</af:iterator>

The af:iterator component iterators over a binding called TestWilfredViewIterator. For each iteration it creates a variable "row" that can be used in the child components of the af:iterator.

The first child component is an af:panelheader to show a header for each new category. It's text property uses an EL expression #{row.category} to get the category text from the current row. The rendered property uses an EL expression to call out to a managed bean. That bean contains the logic if the header should be shown or not. It determines this by comparing the category with the category of the previous row. If it changed, the header should be printed otherwise not.

The next child component is an af:selectbooleancheckbox to include a checkbox input element. It's text ("label") uses an EL expression to get the description from the current row. The value is bound to the TrueBool transient attribute we added earlier. The setter of that transient attribute sets the value of the Bool attribute to either "Y" or "N".

The page definition file contains the binding declarations:

XML:
<executables>
    <iterator id="TestWilfredViewIterator" Binds="TestWilfredView"
              RangeSize="-1" DataControl="AppModuleDataControl"/>

  </executables>

It declares a iterator with the ID of "TestWilfredViewIterator". It binds to the ADF BC ViewObject "TestWilfredView" from the data control named "AppModuleDataControl". The RangeSize is set to -1 so all rows are queried and no pagination is used.

The backing bean contains the code to determine if the header should be printed:

JAVA:
public void setChanged(boolean changed) {
    throw new IllegalStateException("do not call setChanged");
}

public boolean isChanged() {
    // get the key of the current row
    FacesContext context = FacesContext.getCurrentInstance();
    Application application = context.getApplication();
    Object key =
        application.createValueBinding("#{row.key}").getValue(context);
    // compare this key with the key of the previous call (bean can be
    // called multiple times for same row)
    if (!key.equals(previousKey)) {
        // new key, compare categories
        Object category =
            application.createValueBinding("#{row.category}").getValue(context);
        changed = !category.equals(previousCategory);
        // remember category for next call
        previousCategory = category;
    }
    // remember key for next call
    previousKey = key;
    return changed;
}

The managed bean needs both a setter and a getter for the boolean property. We don't really need the setter, but it has to be there to be able to reference the bean property from an EL expression. Without the setter, it is not a bean property and you cannot reference it from EL.

It turns out that this method is sometimes called multiple times for each row of the af:iterator component. This requires some additional handling in the java code. You cannot just assume that the next call of the method also represents the next row of the af:iterator.

So, the code first gets the key of the current row of the af:iterator component. The key is compared to the key from the previous cal to isChanged(). If the key has changed (or previousKey is null), we know we have found the next row of the iterator. We then continue to get the category of the current row. We compare that to the category of the previous call to isChanged(). If it is different, we set a boolean property to indicate this row has a different category than the previous row. We need to store this in a property to make sure that subsequent calls to isChanged() for the same ViewObject row return the same result as the first call for that particular row.

That's all there's to it. Just one last thing, to make the story complete. The managed bean declaration in the faces-config.xml:

XML:
<managed-bean>
    <managed-bean-name>CategoriesBean</managed-bean-name>
    <managed-bean-class>com.example.sandbox.view.beans.Categories</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.