Monday, June 16, 2008

Wow...

I know the title of this blog entry seems a little weird, but after the odd experience I just had with ADF, all I could say was "wow".

The sequence is long and drawn out, but I will try to recount the steps:
1. I was experiencing what I think is a bug with dialogs and the partial page rendering on a return from a dialog interacting with af:selectOneChoice within an af:table. After you return from the dialog, all your drop-down lists get cleared of their current value for some reason.
2. I took this as a bug and decided to try to work around it.
3. I discovered that even though the value of the list would clear, the underlying value the list was based on was still there. This explains why other components (like af:inputText, af:outputText, etc) show their values just fine after returning back from a dialog and doing a PPR.
4. So I thought, why not use javascript to reset the selected value of the list?
5. Then I found out af:selectOneChoice manifests its options tag with sequential values even if you give it other values programatically by basing the selectOneList on a list of SelectItem's...with non-sequential values. In otherwords if you look at "View Source" (in IE parlance) at a select list generated by an af:selectOneChoice, you will always see the value attribute in the option tag say 1, 2, 3, 4, 5, ... regardless what you may have done in your backing bean. So if you created an ArrayList of a single SelectItem(new Integer(5), "five"), the HTML would come out ...at least: that was my experience. I am reasonably sure that is what happens. I would have been really pleased if that is *not* what happens...so I worked it for a while.
6. I then discovered the plain-ol' JSF component f:selectOneMenu (the counterpart to af:selectOneChoice in the ADF Faces world). This produces HTML, the value of which matches the SelectItem you create to back it up...so...
7. You can reset the values with JavaScript...
8. That was almost the end of my ordeal, except that I also found an old trick I used on tables from Steve Muench does not work in this scenario. Have you ever used something like the following as a value binding in a list's value property?

#{<backingbeanname>.<hashmapname>[row.<attribute>]}

Angle brackets (<>) are a meta descriptor.

I think this is from Muench example 71.

When you pass a value in with the square brackets, you can override the "get" method of the HashMap (anonymously, I think it's called) so that, although your presentation component (i.e., the drop-down list) is saying that its f:selectItems sub-component has a HashMap to back it up, it actually has whatever the overridden "get" method returns to back it up.

9. Only trouble is...f:selectOneMenu is not that smart. It thinks this is a HashMap backing this f:selectItems up. af:selectOneChoice does not have a problem with this, but we can't use that component here, right?

10. So we use an approach that creates some List attributes in the backing bean to make accessor functions for.

At any rate, this gives us our list. And when you return from a dialog and the value is reset you can write javascript to reset the selected value to a hidden field which contains the value it should be set to, and which uses af:hiddenField with a value of #{row.whateverFKyouneed}

:-)

Tuesday, June 10, 2008

Entities revisited


Hey folks,


I had an interesting problem which you might be interested in knowing about.


The application I am building currently has a page where you open a dialog and can edit a particular child record. This update screen allows the user to change (among other things) the FK to the parent view object which is on the page the dialog returns to.

There is a little pencil icon. This opens the dialog. Save in the dialog window closes the window and saves the changes.

One of the change they can make as I indicated is to the parent data, which is the designation which parent the child record has.

The interesting thing here is that because I am using drop-down lists, I do not have direct access to the FK value when I need it. Specifically if they change the FK value I do not have the new value. If I use value change listener the new value there just shows the integer index into an array. The way to get at the value is to let a cycle go by and catch it once it has been set with a binding for the iterator. But I don't want to (or can't) wait that long. I need that new value now!

When I change the FK value, because of the way ADF automates coordination between parent/child VO instances, the new record is quickly lost! If I look at the current record in that VO instance fairly quickly after the change has been made, this binding layer says my child/FK record no longer exists under that parent/PK. But I really need that new value.

So where is it? Where can I go look? I know it is not totally lost because the child ends up in another parent; but right when I need it I can not find it.

So where to look: in the entity cache. How do we do that?

In the VO Impl code for the child I have code that does the following:

the first line gets the entity definition for the view object. I get the definition for the first entity associated with the VO because I know the VO only has one entity associated with it. Next I get the app module (again in my app there is only one), and use that to get the particular entity I am looking for. So I use findByPrimaryKey where I plug in the EntityDef and the Key for the particular VO row I am looking for. Once I have found it I get the attribute I am interested in. ParentFKId, in this case, is the FK which points back to the master record. So now I have my new value!

Yee haw!!

Thursday, June 5, 2008

JVM version for AS

This short commentary is for a bug that has bitten me twice in recent ADF projects.

In the Oracle Application Server 10g, in the latest patch level, the default JVM that is used is 1.5.0_06-b05).

If you are getting something in your logs that looks like a compiler error, you might upgrade your JVM to 1.5.0_10 or above (staying with 1.5, I suppose). Oracle is aware that this gets rid of this problem. But since there is no AS 11g yet, my ADF development is still 10g.

On two different recent projects I have had problems. Both times in the logs it looks something like "...Current CompilerTask: opto: 602 oracle.sql.NUMBER.toBytes(Ljava/lang/String;I)[B (1034 bytes)..." The java VM would give an EXCEPTION_ACCESS_VIOLATION and restart itself which ended whatever we were doing. There were also indications that something called "PSYoungGen ...fromSpace" was all used up. The sysadmin here tried various adjustments to memory usage but none of them really helped much.

Hope this entry helps someone.