Thursday, October 25, 2012

Java RMI

The Java Remote Method Invocation (RMI) system allows an object running in one Java virtual machine to invoke methods on an object running in another Java virtual machine. RMI provides for remote communication between programs written in the Java programming language.
That is the definition of RMI provided by Oracle on this page. So, now let's have fun with RMI.

We will create two classes that act as a client and a server. The client consumes object provided by server. First we create the object which is a POJO that implements Remote and Serializable. All the methods that are accessible from client (which are public methods) should declare RemoteException.



Next we create the client. It does the following things in order: Locate remote server host which in my case is localhost, lookup User object, and then update user's address. A note here is that the update is not persisted to the object on server, it is kept locally.



Now we will take a look at the server class. The server first will create a registry at port 1099. It then creates a User object and bind it to the "user" registry. After that, it will execute infinite loop while waiting for user's interaction.

If user types 'a', the User's address is updated and the update is available for the next clients looking up for it when they call lookup() method.

If user types 'b', the User object is unbound so that an error is thrown if next clients looking up for it.

If user types 'c', the "user" registry is replaced with new object user2; this is known as rebind.

If user press 'p', it will simply write user's properties to console.



Wednesday, October 24, 2012

ThreadLocal

ThreadLocal is a class that lets you wrap an object inside it so that each thread accessing ThreadLocal will get its own copy of the object. Consider the following example.

Suppose I have a multithreaded application. The main purpose of each thread in the application is to modify an object through long running processes by calling so many methods (OK this is quite unrealistic example :p). Each thread has its own object to modify. We can declare the object variable in the Thread class or Runnable implementation class or pass it around the methods but obviously it is not a good practice and not always can be done. To overcome this, we can use ThreadLocal.

Images below show us how to implement this: First we have the object to be manipulated, in this case it is a POJO.



Next, we will create a main class which has three threads. Each thread is intended to manipulate a User.



Now we will see the Runnable class to manipulate the object. In the run() method we can see that we modify the user's address in another method and try to see if the changes are persisted correctly. In real life, this is the long-running process that calls many methods to modify the User object.



It's the time to see the ThreadLocal variable in UserFactory class. In the UserFactory class we create a ThreadLocal variable and implement it anonymously. The initialValue() is called only once so it is the best place to initiate everything. All other method's names are quite self-explanatory.



The results are shown below. We can see that each thread has exactly one copy of the User object and the User in each thread is modified correctly. ThreadLocal is very convenient to store an object to be accessible throughout the thread.

Thursday, October 18, 2012

Yet Another SQL Best Practice

Just happened to know a best practice to replace NOT IN in SQL using LEFT OUTER JOIN. Consider the following query:
SELECT * FROM a WHERE a.pk NOT IN (SELECT fk_a FROM b)
Nothing's wrong with query above; however, we can make it better by replacing it with:
SELECT * FROM a LEFT OUTER JOIN b ON a.pk = b.fk_a WHERE b.fk_a IS NULL
This can be explained like this: Left outer join uses table "a" as the master. Each row in table "a" will be matched with each row in table "b". If there is no row matched in table "b" for table "a", null will be returned. See an example below:
a b
1 1
2 null
3 3
4 null
5 5
Now in the WHERE clause we state that we are only interested in rows where b.fk_a is null which means we get all rows in table "a" that has not matched any row in table "b".

Thursday, July 5, 2012

Simple Ship Movement using OpenLayers

Tuesday, July 3, 2012

Cross Site Scripting (XSS)

So far when developing a web app, Firefox has been my default browser. However some clients only have Internet Explorer installed on their machine, IE 6 to be precise, no update/patch from the first time Windows XP was installed. No, I was joking, but it's true that for some reason some people don't want to update their browser. Anyway, since IE 6 is quite old, it is vulnerable to Cross Site Scripting (XSS) attack.


Suppose I have a URL address shown above. When user change any of parameters with <script>a, some scenarios occur. As we can see, there are two parameters passed in URL, method and tab. Some scenarios that may occur are:
  1. Changing method parameter with any string including <script>a. This will throw Servlet NoSuchMethodException since method parameter is used by Struts to choose what action method to fire, so this is not XSS case.
  2. Changing tab parameter with any value including <script>a. This one will make the script be executed and an alert with message a is displayed so it is an XSS case.
  3. Adding any parameter. This will not cause any harm since the parameter will not be processed.
So basically the problem is with tab parameter. What does tab do? It is used to choose which element to be decorated.


The value of tab parameter is assigned to activeTab and then the activeTab is used to get element by id. Since value of tab is changed to <script>a, it will be executed first and make the alert popped up.


We can overcome this by replacing any character "that is not supposed to be passed" as shown above. Here is the complete code:


Saturday, June 23, 2012

Lesson Learnt from Oracle - SQL Server

Moving to a new place could bring hope of learning something new. It did happen to me. I have to heavily work with both Oracle and SQL Server. The very first code I have to write was writing a stored procedure. Not my favorite at first but now I’m just OK with it. There are some notes I'd like to write here as a reference just in case I need them again in future.

Oracle Connect By

The first procedure was who-are-your-managers. There was a need to find out who are an employee’s managers, from direct manager all the way up to the top-level manager. To do that there are several steps need to be done.

Suppose we have a table named PERSON which contains information about employees and who is his/her direct manager. The following query is used to get non-top-level employee:

SELECT PK_PERSON,
            FK_PERSON_MGR
FROM (
    SELECT PK_PERSON,
                FK_PERSON_MGR
    FROM PERSON
    WHERE FK_PERSON_MGR IS NOT NULL AND IS_ACTIVE = 1
) NON_TOP_LEVEL_PERSONS
ORDER BY PK_PERSON



After knowing all non-top-level employees we can now use the following query to get all his/her managers:

SELECT ABOVE_QUERY.PK_PERSON,
            CONNECT_BY_ROOT ABOVE_QUERY.PK_PERSON,
            SYS_CONNECT_BY_PATH(ABOVE_QUERY.PK_PERSON,' > ')
FROM ABOVE_QUERY
START   WITH ABOVE_QUERY.PK_PERSON = ‘THE MANAGER IN QUESTION’
CONNECT BY PRIOR ABOVE_QUERY.PK_PERSON = ABOVE_QUERY.FK_PERSON_MGR
ORDER BY ABOVE_QUERY.PK_PERSON

The result is shown below:


There are four things to note from this query:
  1. CONNECT BY PRIOR is used to connect the person primary key and person manager foreign key.
  2. START WITH is used to define who is the root manager. The above result substituted ‘THE MANAGER IN QUESTION’ with PK_PERSON which means ‘anybody can be the manager so just find his/her employees’. This is equal to removing the START WITH clause.
  3. CONNECT_BY_ROOT is used to get the root in the hierarchy. To be clear, see the result of the SYS_CONNECT_BY_PATH.
  4. Last is the SYS_CONNECT_BY_PATH. It is used to display the hierarchy and very helpful if we need to debug.

SQL Server Linked Server

For some reason, the app I’ve been developing needs to pull data out of Oracle and then store it to SQL Server. We decided to use a SQL Server feature called Linked Server. The following picture shows it on SQL Server Management Studio 2008 R2:


Before we can create a Linked Server to Oracle, we need to make sure that the Oracle provider has been installed.



If it is not there yet, we can download the provider from Oracle website or, in my case; it is installed when I was installing Oracle XE.

After installing the provider, we need to make some changes of the provider’s properties, see the following images on how to do that:





Now we can move on to the steps required to create a new Linked Server:
  1. Right click on the “Linked Servers” and choose “New Linked Server”


  2. On the General tab, fill the following data on the form



  3. The complete “Data source” is:
      (DESCRIPTION =
        (ADDRESS = (PROTOCOL = TCP)(HOST = USER-PC)(PORT = 1521))
        (CONNECT_DATA =
          (SERVER = DEDICATED)
          (SERVICE_NAME = XE)
        )
      )

  4. On the Security tab, fill the following information on the form


  5. After we click OK and there is no error thrown then we can test the connection by right clicking the previously created Linked Server.





SQL Server Linked Server OpenQuery

I had problems when writing a query to pull the data out of Oracle to SQL Server. Things like incompatible numeric decimal points and unrecognized Oracle objects (like synonym) are quite annoying. But fortunately there is this guy named OpenQuery that is able to send native Oracle query from SQL Server.


The following is an example of how to use the OpenQuery:


SELECT * FROM OPENQUERY(XE, 
         'SELECT BASE_DT,
                      COUNT,
                      DATA_CTG
          FROM SYS.MARPRO_PROMO_LOG')



The Open Query takes two arguments. First is the Linked Server and second is the query string. The query string is Oracle native SQL which means we can use Oracle clauses or functions.


However, as I said before, I had problem with numeric conversion. The TO_NUMBER comes to rescue the conversion as shown below:

SELECT * FROM OPENQUERY(XE, 
          'SELECT BASE_DT,
                       PROMO_CD,
                       CIF_NO,
                       GCIF_NO,
                       GCIF_CIF_NM,
                       TO_NUMBER(BAL_SA) AS BASE_BAL_SA,
                       TO_NUMBER(BAL_CA) AS BASE_BAL_CA,
                       TO_NUMBER(BAL_TD) AS BASE_BAL_TD
           FROM SYS.MARPRO_PROMO_ACT')

Insert/Update Many Rows

Most likely there is always be a need to insert or update many rows and we can achieve this by iterating cursor. However, it is not recommended because of performance degradation issue. Instead, we can use insert-into-table-select.

INSERT INTO table1
SELECT * FROM table2

The following query can be used to update many rows at once:

UPDATE GIFT_ORDER SET status_order = 'ME'
WHERE gift_order.pk_order IN (
           SELECT gift_order.pk_order
           FROM gift_order_old)


Oracle Over Partition By

I have a table named DELINQ_CASE to store cases data, including the case owner. The next procedure I had to write was to make prioritization of the cases. To do that, the cases should be queried and ordered by WORK_ON_DATE, STATUS_GROUP, and CURRENT_BAL_DESC columns. Then we can select ROW_NUMBER() to be the priority number since the rows are already ordered. However, because the prioritization should be done for each case owner, the query must be run many times. Oracle has a better way to achieve the same result.


SELECT ROW_NUMBER() OVER (PARTITION BY DELINQ_CASE.FK_PERSON_F_COORD_CLR
                          ORDER BY TRUNC (WORK_ON_DATE) ASC,
                                   STATUS_GROUP ASC,
                                   CURRENT_BAL DESC) AS PRIORITY,
       DELINQ_CASE.PK_DELINQ_CASE,
       DELINQ_CASE.FK_PERSON_F_COORD_CLR,
       DELINQ_CASE.WORK_ON_DATE,
       ACTION_CODE.STATUS_GROUP,
       DUE_AMOUNT_CURRENT.CURRENT_BAL
FROM DELINQ_CASE
INNER JOIN ACTION_CODE
        ON ACTION_CODE.PK_ACTION_CODE = DELINQ_CASE.FK_ACTION_CODE_LATEST
INNER JOIN DUE_AMOUNT_CURRENT
        ON DUE_AMOUNT_CURRENT.FK_CONTRACT = DELINQ_CASE.FK_CONTRACT


  • The query above is used to select data from tables DELINQ_CASE, ACTION_CODE, and DUE_AMOUNT_CURRENT. Data from those tables are used to display information about cases.
  • The ROW_NUMBER() is used as the priority number.
  • Instead of ordering the query by WORK_ON_DATE, STATUS_GROUP, and CURRENT_BAL_DESC columns; and then repeat the query for each case owner, we can use Oracle’s OVER PARTITION ORDER. Here we moved the ordering inside OVER clause and then the result is partitioned by the case owner.
Oracle Update from Select

Oracle offers another way to update data from a sub-query. In UPDATE clause, we can replace the table with a sub-query, with some note though: the sub query must contain a primary key; and if it is in a JOIN statement, the first table must contain primary key and second table must contain foreign key of first table.

UPDATE (
SELECT DELINQ_CASE.PRIORITY AS DC_PRIORITY,
             PRIORITIZATION_SCHEDULING.PRIORITY AS PS_PRIORITY,
             DELINQ_CASE.SUGGEST_WORK_ON_DATE AS DC_SWOD,
             PRIORITIZATION_SCHEDULING.SUGGEST_WORK_ON_DATE AS PS_SWOD
      FROM DELINQ_CASE
           INNER JOIN PRIORITIZATION_SCHEDULING
              ON DELINQ_CASE.PK_DELINQ_CASE = PRIORITIZATION_SCHEDULING.FK_DC
      )
SET DC_PRIORITY = PS_PRIORITY,
        DC_SWOD = PS_SWOD;


In the query above I tried to update two columns from a sub-query. The DELINQ_CASE table was joined to PRIORITIZATION_SCHEDULING table on their PK and FK. Since the sub-query contains a primary key, in this case primary key from DELINQ_CASE.PK_DELINQ_CASE, we can update any column on it. In my case I need to update two columns of DELINQ_CASE with two columns of table PRIORITIZATION_SCHEDULING.

Saturday, June 16, 2012

The objectlabkit Comes to Calculate Working Days

There was this requirement for my project to calculate delivery date estimation. The delivery date is estimated to be 40 working days, in this case I have to exclude Saturday-Sunday and any holidays.

Fortunately there is a library from sourceforge named objectlabkit which can be found here. The latest version was 1.2.0 and I would like to share here how it helped me out:

Create a set of holidays. This is a list of holidays to be excluded from working days.
Calendar firstHoliday = Calendar.getInstance();
firstHoliday.set(Calendar.DAY_OF_MONTH, 18);
firstHoliday.set(Calendar.MONTH, Calendar.JANUARY);
...
Set<calendar> holidays = new HashSet<calendar>();
holidays.add(firstHoliday);
holidays.add(secondHoliday);
Create start and end calendar as a boundary.

In some condition, the holidays are supplied by a service which we can not control and the list could contain holidays from 1990 to 2020 while we are only interested in holidays in 2012. That is why we need the start and end calendar as a boundary.
Calendar earlyBoundary = Calendar.getInstance();
earlyBoundary.set(Calendar.DAY_OF_MONTH, 1);
earlyBoundary.set(Calendar.MONTH, Calendar.JANUARY);

Calendar lateBoundary = Calendar.getInstance();
lateBoundary.set(Calendar.DAY_OF_MONTH, 31);
lateBoundary.set(Calendar.MONTH, Calendar.DECEMBER);
Create an object named HolidayCalendar and register it to CalendarKitCalculatorsFactory.

After creating the boundaries, we have to register the holiday list and the boundaries to an object of type CalendarKitCalculatorsFactory. We need to supply an id when registering to the object so that we can request a DateCalculator object from it later.
HolidayCalendar<calendar> holidayCalendar = new DefaultHolidayCalendar<calendar>(holidays, earlyBoundary, lateBoundary);
CalendarKitCalculatorsFactory.getDefaultInstance().registerHolidays("ID", holidayCalendar);
Get DateCalculator object from CalendarKitCalculatorsFactory by supplying the previously registered id.

The only thing to note here is the HolidayHandlerType constant. In this example I use FORWARD because when the estimated delivery date falls on either Saturday-Sunday or holidays I want the estimated delivery date to be the next available working day.
DateCalculator<calendar> dateCalculator = CalendarKitCalculatorsFactory.getDefaultInstance().getDateCalculator("ID", HolidayHandlerType.FORWARD);
Set the start date.

We need to set start date when the calculation must begin.
Calendar startDate = Calendar.getInstance();
dateCalculator.setStartDate(startDate);
Set the span of how many working days the estimation is supposed to be calculated which in my case is 40 working days.
dateCalculator.moveByBusinessDays(40);
 To get the result use getCurrentBusinessDate() method.
dateCalculator.getCurrentBusinessDate();

Friday, February 10, 2012

Lesson Learnt from iPhone Development

Last week was quite tough for me dealing with the project I was working on. The project was quite simple actually. It was released on App Store and the client decided to make minor changes to the application. I made the requested changes and the application was resubmitted to the App Store. Then we got Apple's email saying that the app was rejected. The email said:

"We found that your app does not follow the iOS Data Storage Guidelines https://developer.apple.com/icloud/documentation/data-storage/, which is not in compliance with the App Store Review Guidelines https://developer.apple.com/appstore/resources/approval/guidelines.html#functionality.

In particular, we found that the app is storing too much data, which can be recreated, in the incorrect location."

I have to admit that I don't visit Apple Developer Portal regularly to check if there are any update on their Developer Guidelines. So the thing is our data was stored in document folder and I need to move application's data to library/cache folder for prior iOS 5.0.1 and setting "do not back up" attribute for iOS 5.0.1 above. Thanks to iCloud, iSun, iMoon and whatever it is on the sky above.

There was another thing screwed me, the core data. Core data needs versioning if you happen to change the data structure like adding columns, changing relationships, renaming tables, etc. Apple has documentation about it but don't expect everything goes smoothly as there are many things undocumented. If you find any errors, stackoverflow.com is your help.

Last thing is, I think it is always a good idea to introduce a User Default value that holds your application version early when you start developing your app. It is useful if you need to trace what application version installed on a device. Usually you need this when there are any update for your app.
 

©2009 Stay the Same | by TNB