Thursday, 30 October 2014

Groovy expressions in BC4J - how to debug them?

Today I'd like to share how to debug Groovy scripts in BC4J. At the beginning you must be aware that it is not possible to debug it step by step. But you can help yourself and print comments to the console in the runtime.

Two approaches are possible. First bases on Debugging groovy in ADF post. In short few words, in Model project you need to create a Java class and use it in Groovy:

But what if the expression is much more complicated. Ok, you can call it inside the expression. There is also another way to print a line in the console in Groove - use print keyword.

And, as usually, rendered page and logs output at the end of the post.

According to ADF 12.1.3 features, in 12c it'll be possible to debug it in JDeveloper :)

Wednesday, 29 October 2014

debugging EL expressions in your application

Debugging java code is relatively simple. But sometimes the stack trace which you can get is unreadable. You see a lot of lines from the core of the framework and... nothing more. No additional hints where to search for the cause. But stack trace contains a lot of UI-related classes. The reason may be in the EL expression.

One approach is to comment all UI components on the page and check which expression generates an error.

Second approach is a try to trace processed EL expressions on the page. Pages are usually very complex and usually contain many EL...

It is possible to override the default EL resolver in your application. First of all, please create the class that extends abstract ELResolver class or one of its subclasses. In this example I've used MapELResolver (reasons why I've used it you'll find in the documentation).

Then point it in faces-config.xml, as shown below:

I've decided to override getValue method becasue usually an error will be thrown there.

Please note, that this is only a simple implementation that I've used to solve my problem. To fulfill the example, the page that will be examinated.

It bases on DEPARTMENTS table in HR schema. Finally, logs from the application after opening the page:

Hope it'll simplify your debugging processes in the future :)

Friday, 17 October 2014

differences between getPostState() and getEntityState()

If you don't pay a lot attention to the subject of this post it'll sound the same. First of all what is the role of an entity. It is something like a mirror image of database table which takes a part during object-relational mapping process. It could contain transient attributes which aren't persisted. It can be based on other database objects than a table. But more or less we can understand an entity as database table definition in ADF.

ORM role implies on it states. I think that everyone understand that the state machine implemented there will be quite complex and the transitions will depends on operations performed on the entity. It is illustrated on the graph below:

For both of the cases the graph look similar but the meaning of the states is a bit different. Entity state represents corellation between object attributes value and the database. Post state is related to database transaction itself.

Lets deeper look to entity state first. There is no default initial state for the entity. There are two states that can be assumed as defaults depends on origin. STATUS_NEW, with byte value equal 0, while current entity is created in the middleware and will be commited within the database transaction. STATUS_UNMODIFIED, byte value 1, if the current changes entity has been commited or it has been synchronized with database (read from the database).

After at least one attribute is set, entity goes to STATUS_MODIFIED (2). STATUS_DELETED with 3 byte value is when a row will be deleted. The last option is STATUS_DEAD (4). Entity has been created and after that removed within the same db transaction or it has been deleted and DELETE DML operation has been performed on the database.

Post state holds information for the transaction manager what have already been done with the data within database transaction. Post state is new when a row is created in the middleware and waits to be commited. If you delete such row it'll go to STATUS_DEAD. STATUS_MODIFIED and STATUS_DELETED are also markers for related DML operations. Interesting is the STATUS_INITIALIZED with -1 value. It excludes the row from the database transaction, so it marks it as temporary one.

These two states are tightly coupled but usually you won't need to worry about it. Framework itself will carry on the transitions. The problem that i've struggled with was while doDML entity method thrown an exception. Framework thought that the entity has been commited (getPostState()==STATUS_UNMODIFIED) but getEntityState() was still STATUS_NEW.

Thursday, 2 October 2014

resolve first and last row in the af:table using varstatus

During my current project i've been asked about rendering a button for first and last row in a table. There is very simple way to achieve that without a single line of Java code. The keyword to the success is varStatus. I've prepared simple application where on the testPage i've drag&dropped sortable and filterable read only table. Also i've added few columns where varStatus properties are displayed.

What can be noticed here:
  • begin always returns 0, it's the index of first element in the collection
  • count returns the number of objects in the collection for the current step
  • current returns the reference to the current row (in the iterators loop)
  • end is supposed to return index of the last element - unfortunately it returns null
  • last is supposed to return true for the last element and false otherwise, it's null (see bug: varStatus.last working?)
  • index returns row index, could be used to display order number value for each row as #{vs.index+1} because it starts from 0
  • step is always 1 - each row from the collection should be displayed
OK, so what needs to be done to properly point the last row? Just small and simple trick:

You need to compare current row index with row count in the collection #{bindings.TheNameOfTheIterator.estimatedRowCount==vs.index+1}. The screenshots above presents filtered collection. Filtering and sorting don't corrupt the solution.

Please notice that varStatus is not only related with <af:table> but also with other components like <af:iterator> or <af:forEach> and its attribute set (and returned values) may differ there.