Sunday, May 9, 2010

JDeveloper 11g PS2 Update - Custom Declarative Components in ADF Faces Rich Client

Thanks to my blog reader, I received comment for blog post - Custom Declarative Components in ADF Faces Rich Client. This post describes how you can develop custom declarative LOV component, that comes together with description text. As reader says - provided sample application works with JDeveloper 11g PS1, but not with latest JDeveloper 11g PS2 release. LOV value wasn't refreshed and not stored to database. I fixed it to work in latest PS2 release, will tell you what update is required.

Download working updated sample application - AdvancedLOVComponent2.zip.

So, what's new now? We should take a closer look into declarative component parameters. Before, I was passing LOV model and value attributes as separate Object type parameters - it doesn't work anymore. Instead, now I need to pass one attribute for LOV, of type oracle.adf.view.rich.model.ListOfValuesModel. I will use this attribute value for declarative LOV component:


You can see, inside declarative LOV component, I'm referencing LOV model, value and label directly from declared LOV attribute:


Before, separate attributes of type Object and String were declared for this purpose. Description value comes as it was in previous version - as separate attribute:


We need to package updated declarative component into JAR library, and refresh consuming project:


Now our custom LOV contains only two custom attributes - one for LOV model and another for description text. LOV model is referenced directly from Page Definition attribute: #{binding.DepartmentId}:


Here we go - declarative LOV component works again - it brings LOV and description values:


User can select new value:


LOV and description text will be refreshed accordingly - updated data can be stored into database:


I should say, updated declarative component design is much better now - it is enough to pass LOV model value and it works.

15 comments:

Mehdi said...

Dear Andrejus

Thanks for your helpful blog.

I have the same problem as mavell. I had a component in JDeveloper 11.1.1.1.0 including 4 LOVs. It worked well. We have recently immigrated to JDeveloper 11.1.1.2.0, and the trouble began. I simplified using just one LOV, but it didn't work yet. I had two attributes for each LOV, one of type String for its value and one of type ListOfValuesModel for its model.
Something like this:

<af:componentDef var="attrs" componentVar="component">
<af:inputListOfValues label=""
id="lovGeneral"
value="#{attrs.generalValue}"
model="#{attrs.generalModel}"
partialTriggers="lovGeneral"
autoSubmit="true">
</af:inputListOfValues>
<af:xmlContent>
<component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
<display-name>selectAccount</display-name>
<component-class>component.SelectAccount</component-class>
<attribute>
<attribute-name>generalModel</attribute-name>
<attribute-class>oracle.adf.view.rich.model.ListOfValuesModel</attribute-class>
</attribute>
<attribute>
<attribute-name>generalValue</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
<component-extension>
<component-tag-namespace>component</component-tag-namespace>
<component-taglib-uri>/mcfsComponentLib</component-taglib-uri>
</component-extension>
</component>
</af:xmlContent>
</af:componentDef>

and the usage was like this:

<mcfs:selectAccount id="selectAccount2"
generalModel="#{bindings.AccAccount.listOfValuesModel}"
generalValue="#{bindings.AccAccount.inputValue}"/>

I changed it using just one attribute of FacesCtrlLOVBinding type. I got both value and model from it. It didn't work too.
The component:

<af:componentDef var="attrs" componentVar="component">
<af:inputListOfValues label=""
id="lovGeneral"
value="#{attrs.generalListBinding.inputValue}"
model="#{attrs.generalListBinding.listOfValuesModel}"
partialTriggers="lovGeneral"
autoSubmit="true">
</af:inputListOfValues>
<af:xmlContent>
<component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
<display-name>selectAccount</display-name>
<component-class>component.SelectAccount</component-class>
<attribute>
<attribute-name>generalListBinding</attribute-name>
<attribute-class>oracle.adfinternal.view.faces.model.binding.FacesCtrlLOVBinding</attribute-class>
</attribute>
<component-extension>
<component-tag-namespace>component</component-tag-namespace>
<component-taglib-uri>/mcfsComponentLib</component-taglib-uri>
</component-extension>
</component>
</af:xmlContent>
</af:componentDef>

and the usage:

<mcfs:selectAccount id="selectAccount2"
generalBinding="#{bindings.AccAccount}"/>

I read your post, and I replaces FacesCtrlLOVBinding with ListOfValuesModel. but it didn't work as well. Do you have any idea what my fault is?

Thanks for reading mu novel ;)
Mehdi

Saikiran said...

Hi,
I created a Custom Declarative component, which has a panel header, but i wanted to expose the binding property of the panel header, so i added a attribute of type RichPanelHeader, and used it in bindings of the panel header, but i am getting following error,
Unserializable value:RichPanelHeader[UIXFacesBeanImpl, id=dc_cnt_ph1] for key:PropertyKey[phBinding]

is there any solution?

Peter Olingo said...

A quick one I was able to create ViewObject using stored procedures but when I drop it as inputListOfValues on jspx it appears at af:outputlabel in running mode.
What am I not doing on ViewObject.
Thanks in advance.

Don said...

Saikiran,
try setting the binding to
binding=#{requestScope.myBindingName}
then you can retrieve it from requestScope.

Piotr said...

Hi,
This component is a great job, but I found a littel bug. When You try to use advance query and add two filter on the same field, in Your case DepartmenName. Then press search everything is ok. But trie to change one filter value and one more time press search. It doesn't work as the first time. The component doesn't see changes. What I found and it's vrey strange, this work only for field that is first in the view object. I now it's strange and I've check it few times. The problem occures only for listOfValues. Have You any idea what is going on with that component and how to fix it?

Regards
Peter.

Andrejus Baranovskis said...

Hi,

Did you tried to test same behavior with standard LOV, does it work?

Which version of JDev you are using?

Andrejus

Piotr said...

Hi Andrejus

I've tested also standart adf component inputListOfValues without declarative component, but it was placed in a row of a table and it doesn't work.

My version of jdev is Studio Edition 11.1.1.3.0

Peter

Andrejus Baranovskis said...

Okej, so its reproduced even for basic LOV component, not only declarative. Can you test same with PS3, may be its fixed?

Andrejus

nms said...

Can this declarative component be used inside by changing attribute hints?

Andrejus Baranovskis said...

Yes, should be possible.

Andrejus

Sandy said...

Hi Andrejus,
Thank you for the blog.
I created my own foobar custom component. I deployed it and added the adf lib jar to my project. Now I want to be able to distribute this to other people without just passing the jar file. In other words, maybe make it available as an extension from the update center and when someone picks it up, i want jdeveloper to take care of loading the libraries for my foobar component. I'm using jdev 11.1.2. Do you have suggestions about this or any documentation on how to go about this ?

Thanks,
Sandy

Andrejus Baranovskis said...

You should contact Oracle, if you want to make your extension available from Updates Center. Then it will be available for all Oracle JDeveloper users in the world.

Andrejus

Anonymous said...

Hi,
Nice component!
But it seems there is a strange bug...
With your exemple, if I put 20 and I press TAB Key, the LOV research Popup appears with 20 and 200. I choose 20 and both input and output fields are populated. OK.
Now, I put 40 and I press TAB Key : the component put the previous value (20). I try another value and it put again 20.
This bug appears only with TAB Key. If I put value then I click on another field it works good.

I would like to modify this LOV component to focus next field when using TAB Key. I try something like it is explained here : http://blogs.oracle.com/jdevotnharvest/entry/how-to_control_the_keyboard_tab_behavior_in_a_lov_field
But, whith autoSubmit=true, the LOV search is executed and the focus is set on the LOV search buton. (and I have the bug).

Is there a solution to keep autoSubmit=true but without the LOV search query automatic execution?
or a way to populate the outputfield (departmentName) without setting autoSubmit=true?

I'm not sure I am very understandable...

I use JDevelopper 11g release 2. (11.1.2.0.0).

Thanks,

h0s

Anonymous said...

Ok I found a solution to my problem.

I set inputListOfValues component's autoSubmit to false.

Then I add an listening to "onBlur" events.

And in the javascript code executed on blur, I call an AdfCustomEvent wich do nothing.

I think this call refresh UIComponents or something like this, so the outputTextField is populated with the good value.

And without autoSubmit=true, I have no more problem with the LOV search execution or I don't know what.

h0s

Zinov said...

Hi Andrejus:
I want to know how to build a declarative component with a java class associated. Something like ViewObjects with ViewObjectImpl. I want like to access to all attributes of my declarative component throw my java class. So, if my declarative component had a LOV, I want to have an access like this myJavaClassInstance.LOV..... . Can you give an idea. Regards. Zinov

can you reply this question to zinova1985@gmail.com or give an url of your blog to see the answer?
Best wishes.
Ivan Zinov