Vgo Software


And now Microsoft is in the game...

A long while back in 2011, I wrote a post about Google's purchase of Motorola.  In the past couple of days came the news that 2 years later Microsoft has purchased the Nokia devices and services business.  If Google was late to the party back in 2011, Microsoft is going to have a hell of a time playing catch up in 2013.

Their much hyped Surface tablets did not quite strike a chord with customers and Microsoft is in a much different position than Google was back then.  In 2011 Google had a modestly successful Android operating system and was suffering from a fragmentation problem (still a bit of a problem, BTW).  Their acquisition of Motorola should lead to Google doing it's own manufacturing of phones that they can ensure run the latest and greatest version of their Android OS with all the best bells and whistles.  That may be just starting to happen now.  Although this won't solve the fragmentation problem, it will allow them to showcase Android.  Lately they've used deals with LG and ASUS to accomplish the same.

I don't think the problem with the Surface can have the same solution - purchasing a hardware manufacturer.  Unless this purchase allows them to create a better product at a less expensive price point, they are still going to have problems getting customers to buy into it.  If anything, the Surface proved that Microsoft is too late to attract customers with an overpriced, inferior product even if it ties in well with their desktop OS.

I, for one, am really interested to see if this acquisition can give Microsoft a boost in the mobile department but I really think the only way they are going to do that is by having a product that really wows its potential customers.  Enough so that they will switch (probably once again) to a whole different platform.


System modernization and System design

Modernization efforts come in varying levels of complexity. We recently undertook a modernization initiative for a client who wanted to migrate their existing database portfolio from Sybase to Oracle. While Oracle's SQL Developer helps with migrating the database and its various objects, the applications talking/connecting to these databases have to be remediated manually.  It is during such times we see the importance and value of time invested in good system design.  

A lot of the applications we encountered for remediation followed a consistent design. At a high level, one could view that design as an application made up of a stack of three horizontal layers - UI, Business Domain and Data Access. Most applications also consisted of a testing layer could be seen as a vertical layer, that tested one or more horizontal layers. For the most part, the unit tests (part of the Test layer) would test the Classes of the data access layer which comprised of Data Access Objects (DAO's) and Data Transfer Objects (DTO's), but because of the clean separations of the various layers you could in theory test any layer. While I am not going into the details of what each layer does, it’s not hard to guess what each layer might be doing.  

What I described in the last paragraph are two very simple things, 1) Structuring or designing the application layers such that boundaries with interfaces are enforced and in place and 2) consistently following a simple in design/structure across multiple applications.  In my opinion, as simple as these things are they matter a lot in the long term. The code written for one of these layers could be horrible but if the boundaries are enforced with well-defined interfaces, a change effort -of any kind- could be undertaken fairly easily.  An example could be that DAO layer is implemented to work with a specific RDBMS product today but in the future can be modified relatively easily to incorporate a ORM based RDBMS neutral approach or  a different RDBMS which was our case. I am giving an example of the DAO layer but this idea can be expanded to any of the layers that you find in today’s business systems.

I think in this day and age, business systems should be architected and designed for change more than anything else.  And change is best accommodated when systems are simple to deconstruct. When I write code, I deliberately re-prioritize why I am writing it, at first, for me or somebody else to read and understand, and then for the computer to execute. The computer could care less how you wrote the code. If it was just for the computer you might as well write in 0's and 1's. Note that this does not mean sacrificing on time or space efficiency choices. The same way when making design choices I put them in the context of long-term change and maintainability.

More often than not, these simple steps result in software that is relatively easy to maintain for most non-edge case scenarios. Code and Design that is fluid and can adapt over time is one of the most important things, especially in today’s time when requirements and business needs change so quickly. So the next time you work on a design or write code deliberately, change your thought process and see if that results in a better design. Worst case, you can be confident that you have explored different options before finalizing something.


Problem with Web Services in ADF - Resolved

So I spent some time working with a client last week who was attempting some interesting things with ADF.  For one, this guy was a beginner to ADF and Java and someone just threw him into the deep end.  It wasn't just "create a couple pages to allow users to update this data", it was create a web service, and not just a web service but a service that accessed more than one database.  One was an Oracle database, the other a SQL Server database.

Working wtih SQL Server itself wasn't a problem, but trying to get one application that could talk to both at the same time was a problem.  It is supposed to be possible, but it isn't the best way to do things.  The better way is to use a DB Link on the Oracle database itself.

Once we straightened that out, we encountered an error testing a simple web service.  It would try to deploy to the integrated Weblogic instance, but fail in deploymentment with an error that the service implementation class could not be found.

Now the only reason I could think of that it would attempt to deploy and give an error like that after compiling nicely was that the versions of Java were different.  If it was compiling with a newer version of Java than Weblogic was running with, that would be an issue.  I presumed that the issue would, however, also manifest itself when deploying an ADF Web Application.  Especially if it was the same app just being deployed differently.

Turns out presuming anything is a bad idea.  As it was late on Friday and I was getting close to missing my plane home, I asked the developer to send me the log and while getting a ride to the airport I took a look at it on my phone.  I found this part of a line: "C:\Program Files\Java\jdk1.7.0_21\jre\bin\java.exe -client -jar" indicating that it was indeed compiling with jdk1.7.0_21 and trying to deploy to a Weblogic server using a version of 1.6.


I e-mailed back the devleoper and he changed the Compiler "JDK Version Compatibility" setting to 1.6.  Low and behold - problem solved.  And just in time for the weekend too!


ADF ConcurrentModificationException Issue Resolved

So, as I am sure you are aware, a ConcurrentModificationException will be thrown when one thread is iterating through a list and another thread modifies that list.  We encountered this exception being thrown in an ADF Search page, using the search panel.  With a particular LOV, everytime a user searched after selecting a value from the LOV, the exception would be thrown (and then the results returned).

After much head-scratching, we found that another field had two different LOVs tied to it and some logic to determine which LOV to show.  The attribute with LOV causing the problem was used in the logic, however, it was not set as a dependency.  Once it was set as a dependency the problem was solved!

You live, you learn.


ADF View Objects with Dynamic Where Clauses

While working on a recent modernization project I came across a scenario in which a View Object used by a page had a different where clause depending on one of the values passed in.  All in all, not too big of a deal, but because the where clause used a number of parameters and the parameters used changed along with the where clause it introduced some complications.  So to save you the trouble I thought I'd write about a couple of them here.

First of all, it is easy enough to to create a method in an Aplication Module implementation class that adjusts the where clause to what you need using the ViewObject.setWhereClause(String whereClause) method.  To set the parameters you need to use the ViewObject.setNamedWhereClauseParam(String paramName, Object paramValue) method.  What I found was that I had to have the parameters set at Bind Variables in the View Object and they must have their required property set to true, otherwise they are not really bind variables.  

What that means is that to execute the query, it must contain all of the bind variables even if they are not being used.  That means putting them in the where clause all the time.  To accomplish this for bind variables that were not used, I just put something like "and :par1 = null" and set the value to null using the above method.

This works fine except that since the bind variables are not in the original query definition another problem was encountered.  As soon as the task flow opened, the first thing it had to do was run the method I defined in the Application Module, unfortunately that did not happen.  Instead the first thing that happened was that the View Object executed and returned an error because the bind variables were not in the query.

Apparently in order for my method to work, I needed a page definition file that allowed my method to access my View Object's iterator.  Because this iterator was in the page definition file, ADF executed the query upfront even though nothing that used it was being called yet.  In order to fix this I set the refresh property of the iterator in the page defintion to "never".  This means that the iterator will not execute unless refresh() or execute() are called programattically on the View Object.  Of course this happens in the Application Module method that sets up the where clause after the where clause has been defined with the parameters in it.

That's it, simple enough once you realize what is happening, but a little frustrating before that light bulb goes on!