Thursday, August 30, 2012

Dealing with Date format

By default whenever a date field is dragged onto the page, an <af:convertDateTime> component is added to it which decides the pattern and other prerequisites (like Locale,Timezone etc) . So the simplest way to change the display pattern for date is to -

1.Select <af:convertDateTime> component.
2.Edit the Pattern
3.Change it to your required pattern ,say dd/MM/yyyy as in my case.

 
But this has to be done wherever the date field is present , so instead of changing the format on every component it is recommended to be changed from the model layer itself, so that changes reflect at all levels.


Convert Date at Model layer-

Date format can be changed at the Model layer either in EO or VO level attributes. If we change it in the EO level, it gets reflected in VO level as well.
By default on selecting Format Type :Simple Date under UIHints tab in EO for the date attribute, we can select
the required date format from the preconfigured format list provided .


 
But what if we want custom format like dd/MM/yyyy or dd/MMM/yy ?

So in this case though we can add custom pattern on the view page using <af:convertDateTime> (discussed earlier),but it won't be available in case of search queries ie to format the pattern for the bind variables (search fields).
So for such requirement, we need to Locate formatinfo.xml under the following directory( For Jdeveloper 11.1.2.1.0)

C:\Documents and Settings\[USER]\ApplicationData\JDeveloper\system11.1.2.1.38.60.81\o.BC4J\formatinfo.xml

 
Edit formatinfo.xml and modify the required date class:


  1. <DOMAIN CLASS="oracle.jbo.domain.Date">
  2. <FORMATTER name="Simple Date" class="oracle.jbo.format.DefaultDateFormatter">
  3. <FORMAT text="yyyy-MM-dd" />
  4. <FORMAT text="yyyy-MM-dd G 'at' hh:mm:ss" />
  5. <FORMAT text="EEE, MMM d, ''yy" />
  6. </FORMATTER>
  7. </DOMAIN>


After we add required format using <FORMAT> tag the code would look as follows:


  1. <DOMAIN CLASS="oracle.jbo.domain.Date">
  2. <FORMATTER name="Simple Date" class="oracle.jbo.format.DefaultDateFormatter">
  3. <FORMAT text="yyyy-MM-dd" />
  4. <FORMAT text="yyyy-MM-dd G 'at' hh:mm:ss" />
  5. <FORMAT text="EEE, MMM d, ''yy" />
  6. <FORMAT text="dd-MM-yyyy" />
  7. <FORMAT text="dd-MMM-yyyy" />
  8. </FORMATTER>
  9. </DOMAIN>

Now when we browse through our list of Formats in 'UIHints' tab, we can find our custom format pattern available.


So now we can select dd/MM/yyyy as our format for date and the change reflects to all levels .

 
 Yet another way to change the date format would be to use the Locale specific date formatting .i.e without changing individual date attribute's format.
It can be accomplished by adding the following localization property inside trinidad-config.xml (Present under WEB-INF folder of View Controller)


  1. <formatting-locale>nl-BE</formatting-locale>

This would change all date types present in your project to dd/MM/yyyy from the default MM/dd/yyyy . But the only problem with this is it changes all the Numeric formatting types also to the 'nl-BE' locale (IANA-formatted locale). Other IANA-formatted locale for changing date to dd/MM/yyyy is 'en-GB' .

Note: 
<formatting-locale>:  Defines the date and number format appropriate to the selected locale. ADF Faces and Trinidad, will by default, format dates and numbers in the same locale used for localized text. If you want dates and numbers formatted in a different locale, you can use an IANA-formatted locale (for example, ja, fr-CA). The contents of this element can also be an EL expression pointing at an IANA string or a java.util.Locale object.

Wednesday, August 29, 2012

Reset/Cancel a Form

Sometimes we need to cancel a form or reset all the editable form fields. The following post provides few methods for doing so.

1. Rollback - the traditional way. It rollbacks to the previous state for the changes that are not committed yet.
        It closes all open Row Iterators and executes the View Object.
        Either use it on a  buttons Action Listener or directly drag the Rollback operation from the Data Control.
        Only problem is it rollbacks all the uncommitted transactions instead of only resetting the form field.
        It invokes ROLLBACK from database and executes View Object to return latest data from DB for all  rows.
        This works well when we want to undo multiple changes at once.

2.  <af:resetButton> - Resets the content of a form for all editable components, updating all editable components with the current values of the model on the server.


  1. <af:resetButton text="resetButton" id="rb1"/>
 
3. Using ResetUtils  - It resets all editable value holders present inside UIComponent 'myForm' .The UIComponent is searched for within the component tree and the first one encountered is reset back to the original value.


  1. public void resetActionListener(ActionEvent actionEvent){
  2. UIComponent myForm = actionEvent.getComponent();
  3. oracle.adf.view.rich.util.ResetUtils.reset(myForm);
  4. }

4. Using af:resetActionListener.  Drag the af:resetActionListener component onto the cancel button and set immediate=true on the cancel button so client validation is bypassed .

  1. <af:commandButton text="Cancel" id="cb1" action="#{bindings.Rollback.execute}" inlineStyle="font-weight:bolder;" immediate="true" >
  2. <af:resetActionListener/>
  3. </af:commandButton>

5. Queue an action on an existing button containing  af:resetActionListener attached to it on the page.The button's binding is present in the bean.


  1. public void resetActionUsingQueueListener(ActionEvent aEvent){
  2. //Queue the binded button's action to this button's action event.
  3. ActionEvent actionEvent = new ActionEvent(this.getResetButton());
  4. actionEvent.queue();
  5. }

6. Create instance of resetActionListener in bean and call processAction ()

  1. public void resetAct(ActionEvent actionEvent) {
  2. ResetActionListener ral = new ResetActionListener();
  3. ral.processAction(actionEvent);
  4. }

7.Another way is Cancel by undoing changes - set "immediate=true" on the cancel button.
Open the ViewImpl class and add the following code which first determine whether or not the row is new or an existing row and accordingly either removes/refresh it.


  1. public String getRowStatus(Row row){
  2. DepartmentsViewRowImpl rwImpl = (DepartmentsViewRowImpl)row;
  3. String rwStatus = translateStatusToString(rwImpl.getEntity(0).getEntityState());
  4. return rwStatus;
  5. }
  6. private String translateStatusToString(byte b) {
  7. String ret = null; switch (b) {
  8. case Entity.STATUS_INITIALIZED: {
  9. ret = "Initialized"; break;
  10. }
  11. case Entity.STATUS_MODIFIED: {
  12. ret = "Modified"; break;
  13. }
  14. case Entity.STATUS_UNMODIFIED: {
  15. ret = "Unmodified"; break;
  16. }
  17. case Entity.STATUS_NEW: {
  18. ret = "New"; break;
  19. } }
  20. return ret;
  21. }

Provide the ActionListener ('onCancel') for Cancel Button on the page  -


  1. public void onCancel(ActionEvent actionEvent) {
  2. FacesContext fctx = FacesContext.getCurrentInstance();
  3. DCBindingContainer bindings = (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
  4. DCIteratorBinding iter = bindings.findIteratorBinding("DepartmentsView1Iterator");
  5. Row rw = iter.getCurrentRow();
  6. OperationBinding getRowStatusBinding = bindings.getOperationBinding("getRowStatus");
  7. String rwStatus = (String)getRowStatusBinding.execute();
  8. if ("NEW".equalsIgnoreCase(rwStatus)){
  9. iter.removeCurrentRow();
  10. iter.refreshIfNeeded();
  11. } else{
  12. rw.refresh(Row.REFRESH_UNDO_CHANGES);
  13. }
  14. fctx.renderResponse();
  15. }

8. Custom bean method to reset the UIcomponent (form) :


  1. public void resetAction(ActionEvent aE) {
  2. AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
  3. resetValueInputItems(adfFacesContext,searchForm);
  4. }
  5. private void resetValueInputItems(AdfFacesContext adfFacesContext, UIComponent component){
  6. List<UIComponent> items = component.getChildren();
  7. for ( UIComponent item : items ) {
  8. //resetValueInputItems(adfFacesContext,item); //uncomment in case of nested UIComponents
  9. if ( item instanceof RichInputText ) {
  10. RichInputText input = (RichInputText)item;
  11. if ( !input.isDisabled() ) {
  12. input.resetValue() ;
  13. adfFacesContext.addPartialTarget(input);
  14. }
  15. } else if ( item instanceof RichInputDate ) {
  16. RichInputDate input = (RichInputDate)item;
  17. if ( !input.isDisabled() ) {
  18. input.resetValue() ;
  19. input.setValue("");
  20. adfFacesContext.addPartialTarget(input);
  21. }
  22. } else if (item instanceof RichSelectOneChoice){
  23. RichSelectOneChoice input = (RichSelectOneChoice)item;
  24. if ( !input.isDisabled() ) {
  25. input.resetValue() ;
  26. input.setValue("");
  27. adfFacesContext.addPartialTarget(input);
  28. }
  29. }
  30. } //end -for each loop
  31. }

Sunday, August 5, 2012

Deployment Failure

Case: Recently I came across a deployment error-
[Application MyApp stopped and undeployed from Server Instance IntegratedWebLogicServer]

Remote deployment failed (oracle.jdevimpl.deploy.common.Jsr88RemoteDeployer)
# Cannot run application MyApp due to error deploying to IntegratedWebLogicServer..

Solution :
This Errror may occur when the applications UIModel project has created a web.xml file on it's own.
The only solution I could find was to delete the duplicate web.xml file from the project and redeploy the application. And it worked!

Note:JSRException may also occur in case the connection is not available.