Java7
Java
Graceful URL Redirection with Amazon S3
May 14th
We have two web applications running on AWS Beanstalk which is a Tomcat container PAAS (without Apache HTTPD) and running into the classic problem of being unable to redirect URLs out of the box. Fortunately, graceful workaround exists.
Background of the applications
The buy flow for a typical customer consists of two steps, first by reserving, and then purchasing once the stock has arrived. To do so, they use the Reserve and Purchase web applications respectively.
Each of these applications supports multiple handsets on one web application. I.e. there could be 100 handsets, but only one Reserve and Purchase web application. To do this, each application differentiates one product from another using a GET parameter. E.g. model=iphone5, model=s4, model=1x. You will see more of this later.
Web Application 1 (Reserve Web Application):
The Reserve web application captures reservation information for a handset product which I wish to market, for example it could be Samsung S4, IPhone 5 or HTC One X.
The Reserve web application has the URL reserve.elasticbeanstalk.com. (Fictitious, for illustration only)
Customers who wish to reserve a handset would have to fill up and submit a form using the application’s URL reserve.elasticbeanstalk.com.
For example, for Samsung S4, the URL would be reserve.elasticbeanstalk.com/index.xhtml?model=s4.
If the handset to reserve were to be an IPhone 5, then this URL becomes reserve.elasticbeanstalk.com/index.xhtml?model=iphone5. If you notice correctly, only the value for the GET parameter ‘model’ changes.
Web Application 2 (Purchase Web Application):
The Purchase web application is the second web application that captures order information of a handset product which I wish to sell to my customers.
The Purchase web application has the URL purchase.elasticbeanstalk.com. (Fictitious, for illustration only)
Customers who wish to purchase a handset after reserving would have to fill in payment information through a form using the application’s URL purchase.elasticbeanstalk.com.
For example, for Samsung S4, the URL would be purchase.elasticbeanstalk.com/index.xhtml?model=s4.
If the handset to purchase were to be an IPhone 5, then this URL becomes purchase.elasticbeanstalk.com/index.xhtml?model=iphone5. If you notice correctly, only the value for the parameter ‘model’ changes, analogous to how the Reserve web application works.
Accessing the Web Applications
To reserve a handset, customers could use the Reserve web application’s URL indicating the model, for example, purchase.elasticbeanstalk.com/index.xhtml?model=iphone5. To purchase, customers could use the Purchase web application’s URL in a similar fashion, for example, reserve.elasticbeanstalk.com/index.xhtml?model=iphone5.
Sub Domain launch.java.sg
We have a sub domain launch.java.sg specially elected to cater to this service, this URL would serve as a single access point to customers who wish to purchase and reserve handsets.
For example, if customers were to reserve an IPhone5, then launch.java.sg/reserveIPhone5 would be used. If customers were to purchase an IPhone5, then launch.java.sg/purchaseIPhone5 would be used.
Therefore, we need some kind of redirection for reservations to go to Reserve web application’s URL and purchase to go to Purchase web application’s URL, together with the GET parameter to indicate the model.
Step 1: Create an S3 bucket representing your sub domain URL
This step requires you to go into S3 to create a bucket corresponding to the sub domain, for our case it was ‘launch.java.sg’.
Create two files named “reserveIPhone5″ and “purchaseIPhone5″, upload to the newly created S3 bucket.
Select the object “reserveIPhone5″, in the properties tab, grant an Open/Download permission to everyone. Save when completed.
Do the same for the “purchaseIPhone5″ object.
Select the “reserveIPhone5″ object again, in the metadata tab, add a Website Redirect Location metadata. In the value, enter the URL of Reserve Web Application to reserve an IPhone 5: reserve.elasticbeanstalk.com/index.jsf?index.xhtml?model=iphone5. Save when completed.
Select the “purchaseIPhone5″ object again, in the metadata tab, add a Website Redirect Location metadata. In the value, enter the URL of Purchase Web Application to purchase an IPhone 5: purchase.elasticbeanstalk.com/index.jsf?index.xhtml?model=iphone5. Save when completed.
Go back to the S3 bucket “launch.java.sg”, on the Static Website Hosting tab, select “Enable Website Hosting”. Enter a value for the index document. Save when completed.
In the Permissions tab, grant everyone the permission to list. Save when completed.
In the Static Website Hosting tab, take note of the endpoint URL. This is required to create a CNAME in the later steps.
Step 2: Create a CNAME to the S3 bucket
For me, i am using the CPANEL to add a CNAME to my domain name.
Name: launch.java.sg.
TTL: 14400
Type: CNAME
CNAME: launch.java.sg.s3-website-ap-southeast-1.amazonaws.com
Step 3: Test
Open a web browser, enter the URL http://launch.java.sg/reserveIPhone5. If everything is successful, you should be redirected to reserve.elasticbeanstalk.com/index.jsf?index.xhtml?model=iphone5
After that, enter the URL http://launch.java.sg/purchaseIPhone5. This should be redirected to purchase.elasticbeanstalk.com/index.jsf?index.xhtml?model=iphone5
:)
Java Class Version Number (48, 49, 50, 51 etc) Quick Reference
Apr 11th
Often when you receive some Java Jar files you may come across incompatibility issues when running that on your JRE.
The run-time environment must be the same or higher than the Java version that the Java source codes were compiled using
For example if you have compiled some Java source files using JDK 6, then you need at least a JDK 6 and above run-time environment to execute the Java classes.
Common Java class version incompatibility error message:
(I was trying to run this Java 7 compiled class in JRE 6.
Caused by: java.lang.UnsupportedClassVersionError: com/bim/entityfacade/rela/espagecontent/dao/PageContentEntityFacadeDAO : Unsupported major.minor version 51.0 (unable to load class com.bim.entityfacade.rela.espagecontent.dao.PageContentEntityFacadeDAO)
So whats 51.0? That is Java 7, meaning that the class file was compiled using JDK 7.
Here is the full list:
46 = Java 1.2
47 = Java 1.3
48 = Java 1.4
49 = Java 5
50 = Java 6
51 = Java 7
? = Java 8
Logback is unable to recognize variable substitution For scanPeriod property
Aug 9th
Sometime in November 2011, on discovering a bug with Logback and subsequently filing a JIRA with Ceki.
http://jira.qos.ch/browse/LOGBACK-396
In June 2012, Ceki advised that this will be fixed in 1.0.7. (Current production version as of today is 1.0.6)
http://github.com/qos-ch/logback/commit/ab197e7ac8a7
Original JIRA ticket:
It seems like Logback is unable to recognize variable substitution for certain properties.
For example the scanPeriod property:
Logback configuration:
<configuration scan="${scan:-true}" scanPeriod="${scan-interval:-10 minutes}">
Specified to take default value of 10 minutes of logback property is not defined.
Logback properties:
scan=true scan-interval=30 seconds
This property should override the default configuration of 10 minutes.
Logback error:
java.lang.IllegalArgumentException: String value [${scan-interval:-10 minutes}] is not in the expected format.
According to the Duration API, the duration format is correct.
EDIT: Update - 3 October 2012
As i only had time to check today, it appears that Logback 1.0.7 is already out. Cheers. :) Thanks, Ceki.
Advantage of Disabled Logging in SLF4J / Logback vs Log4J
Jul 18th
Here is an example of the benefits brought forward by disabled logging through using SLF4J / Logback.
Log4J
Object entry = new SomeObject();
logger.debug("The new entry is "+entry+".");
Here are the tasks performed:
- Java calls on toString method on the variable entry to get the String literal representation. Java initializes space in heap to hold the String object.
- Java creates a new String based on the above String, with “The new entry is “ and “.”. Java initializes space to hold the yet newer String literal.
- Java passes on the newly constructed String object as input parameter to Log4J. Log4J checks if the current logging level is DEBUG and above. (assuming it was set to INFO in logging.xml descriptor)
- Log4J does not print out the String literal into the log, since the logging level is set to INFO. (Therefore all the work on 1 – 2 was wasted)
SLF4J / Logback
Object entry = new SomeObject();
logger.debug("The new entry is {}.", entry);
Here are the tasks performed:
Java calls on toString method on the variable entry to get the String literal representation. Java initializes space to hold the String literal.Java creates a new String based on the above String, with “The new entry is “ and “.”. Java initializes space to hold the yet newer String literal.- Java passes on the String object “The new entry is {}.” and object entry as input parameters to SLF4J. SLF4J checks if the current logging level is DEBUG and above. (assuming it was set to INFO in logging.xml descriptor)
- Log4J does not print out the String literal into the log, since the logging level is set to INFO.
Clearly, both computing resources and power in step 1 and 2 are saved in the case of SLF4J / Logback compared to Log4J.
Managing Session Attributes In a Maintenance Project
Jun 7th
This is my first article in the month of June after a break from the last which I have written in March. There is a bug (and there still is) with my WordPress installation where i cannot embed codes (Java codes etc.) anymore.
Have you ever been part of a project where there is little governance over what developers put into session, and to make things worse, there are no standards (in my project this would be primarily my fault because I kept delaying on the deliverable for a standards document :p) to call for what is an acceptable session variable name.
This is quite pertinent to happen in a tightly funded maintenance project where the objective has been to extend the lifespan of an aging legacy application while waiting for newer applications to be built to take over its roles and functionality.
This article covers the topic on the difficulty to track and know the session variables that developers have put into session. (In my project developers introduce at an alarming rate of 20 new session attributes per release)
(Hint JSF developers, you don’t have to be reading this unless your project has been abused, Struts 1/2 developers, read on, its your (our) destiny.)
Today, Developer A knows the whereabouts and functionality of the session variable key MSN, he uses it to hold the MSN of the customer, this eventually gets saved into the database. Tomorrow, Developer B creates another session variable key MSN_PP which he uses for the same purpose, except for to hold the MSN of a customer another sales flow.
We need to have a common knowledge base of the meaning of the session variables, but how do we do so in the most efficient and effective manner? (When all the architects have left the project, the design documents way out-dates) The first idea was a Microsoft word document. But, to serve the purpose here, the idea of a knowledge base for session variables must be as good as it is painless and immediate when it comes to looking it up / contributing to it. The solution must not give the developers the inertia to find out what a session variable does or write down what they know about it. Developers would want to have information without leaving the current screen, and most importantly, accurately with each revision of change.
Because not knowing what is available and it is always more convenient to create new throw-away session variable keys (MSN1, MSN_New, msn_9, tissueWipe_1, tissueWipe_2), we’ll never have a clear picture of what might be the session variable primarily responsible for controlling / holding something.
So we introduce to you two key enablers (henceforth forming the solution), these are not shy to us Java developers, SessionAttribute.java / ESessionAttribute and JavaDocs.
SessionAttribute.java
Like the instinct of a good and responsible developer, our first level of responsibility comes from the way we name our session variables, we strive to give short but predictive variable names to our session variables. E.g. msnInUse, msnList, dslId. We provide a brief write up on what we create the session variables to do for its lifetime in the source code, what know exactly what data they should hold, which flows they appear.
On creating …
1. Give session variable names and keys concise and predictive names.
2. Put all the session variables keys in a central class, SessionAttribute.java.
On using …
1. Check if the session variable key is defined in SessionAttribute.java, if it is, use it. If it is not, create a new one in SessionAttribute.java / identify a suitable candidate for re-use.
On refactoring existing …
1. Check the JavaDoc on what it says the session variable is for, if it fits your description of what you need a session variable to do, use it.
(Senior developers could do more in this section by contributing to SessionAttribute.java whenever we come across a session variable we know what it does, as a lot of existing session variables have been created with painful names, e.g. resHm, flrp_fnn_JK1, it is very hard to decipher what it is doing.)
public class SessionAttribute {
public static final String msnList = "msnlist";
public static final String businessAddress = "add";
public static final String residentialAddress = "resHm"; // This is where i want to really say "thanks to SOSSession.java, i do not need a wild guess what resHm" because it was created ages ago.
public static final String billingAddress = "arbor_add"; // See how easy it has now become to know resHm and arbor_add are actually cousins?
public static final String statusCheckSessionDO = " statusCheckSessionDO" // A complex object
}
JavaDocs
The above (SessionAttribute.java) would not be complete without a good JavaDoc that we can reference / generate (into HTML ones like the one here http://docs.oracle.com/javase/6/docs/api/). More importantly, we are able to contribute and build towards a technical knowledge base in a way universal to Java programming.
This is amicably the most crucial and important part of being a responsible developer – documentation.
/**
* Session variable to <Your one liner analysis of the session variable goes here>.
* <p>
* If you have more valuable information, it goes onto the second line onwards. The first line above should always be concise.
* </p>
* <p>
* Type: {@link StatusCheckSessionDO } <- Does this session attribute key reference a complex data type or a simple String like “yes” or “no”? indicate here.
* </p>
* @since <Since which release?> (e.g. 1 or 5.6b)
* @author <Your name> (e.g. Chin Boon)
*/
public static final String businessAddress = "add";
* {@link StatusCheckSessionDO }is a JavaDocs syntax that will help you generate the following clickable link to fast forward your search, both in an IDE, and on the JavaDoc HTML output.
ESessionAttribute.java
You have heard of me mentioning ESessionAttribute.java but have not seen it being mentioned throughout the article up until here.
As you know, Java 5 gave birth to a new Java class / construct Enum. Enum needs no further explanation, and a whole lot of tutorial and books cover this.
You are right if you are thinking ESessionAttribute.java is the enum counterpart of the above SessionAttribute.java.
But why didn’t you jump straight into providing an enum based solution instead of a class full of static final constants you ask? The answer is simple, most maintenance projects are still “stuck” in the Java 1.4.2 paradigm and as much as they want to do more with enum, these developers just couldn’t. So if you are a “Java 5 and above” developer, spearhead into ESessionAttribute.java, an enum based counterpart of SessionAttribute.java!









