Licence Management for Java Web Applications Using Aspects

December 13th, 2006

This post provides step by setp instruction on implementing license management for Java web applications. I have used open source product TrueLicense for license management and aspects to weave the license verification into the code.

TrueLicense Library Collection(TLC) is a collection of Java packages to securely create, install and verify license for closed source products. TLC is rich in features – License can be perpetual or temporary, bound to users, systems or other entity, free trial period implementation, privacy of license content using password based encryption provided by Java Cryptography Extension (JCE), authenticity of license using digital signature mechanism provided by Java Security API etc.

How to implement License management

What you (Developer) need to do:

1. You already have your web application (say HelloWorld) and you would like to implement License Management. If this is your case, read on.
2. You may want to add a new page for licene management. The client should be able to see the validity of the current license, and instal new license from this page.
3. Write an ascpect to verify license. The pointcut will specify the critical areas of the application. The right approach is to have the licence verification done in every critical functionality of the application. License verification is a ‘cross-cutting’ concern, and hence we can effectively use aspects to weave license verification into our code.
4. Generate private and public key using keytool command.
5. Generate license file. A license file contains encrypted, digitally signed information.
6. Use AspectJ compiler to compile your application.
7. Use a good Code Obfuscator, such as Proguard to guard against Decompilation tools. This is a very important step in real life situtation. If this step is skipped, hackers could exchange your public key and KeyStoreParam implementation with their their own code and bypass the license verification. Since this is a demo app and I’m lazy, this step is skipped. :)
8. Build your application along with the public key.
9. Distribute application and license file to your client. (NEVER give your private key)

What your client needs to do:

1. Pays $$$ and buys your HelloWorld application
2. Fires up the app, navigates to the licenese management page, instals the license file.
3. Uses the app. If the license is expired or not installed, he will not be able to use the application.

Demo Application
The demo application can be used with Tomcat. Download LicenseDemo. Please refer README before using the demo app.

How to use this Demo

1. Unzip HelloWorld-Licensed.zip
2. Run ‘ant clean generateLicense’ from /buildtools folder. This creates a file called sample.lic
3. Run ‘ant clean dist’. This creates HelloWorld-Licensed.war in dist folder.
4. Drop the HelloWorld-Licensed.war file in your webapps folder of Tomcat installation. You are all done!
5. Access the application by http://localhost:8080/HelloWorld-Licensed

First, access the Greetings page without installing license. The error message should be dislayed.
Next, instal sample.lic from the License management page and then access Greetings page. Later, allow the license to expire and access the Greetings page again.

Turkey day is Ubuntu day

November 23rd, 2006

What do you do on Thanksgiving day when you don’t cook turkey, everything is closed, its raining and too cold to go outside? Say bye to Win-doze and welcome Ubuntu.

I’m actually surprised that it has taken a long time to make this move ‘cos I use Linux/Unix a lot at work. Now, it feels great for two reasons:

* Ubuntu is cool and I love it
* No more blue screen of death!

Running multiple JBoss instances on the same machine

August 30th, 2006

Did you ever had the requirement to run multiple JBoss instances on the same machine? Its a trivial task if you exactly know the parameters to be tweaked.

Carryout the following steps with your second instance (This is applicable for JBoss 4.0.3):

* default/deploy/jbossweb-tomcat55.sar/server.xml
o change 8080 to 18080

* default/conf/jboss-service.xml
o change 1099 to 11099
o change 1098 to 11098
o change 4445 to 14445
o change 4444 to 14444

* default/conf/jboss-minimal.xml
o change 1099 to 11099
o change 1098 to 11098

* default/deploy/jms/uil2-service.xml
o change 8093 to 18093

Voila! You’re done!!

Update (04/24/2008):

Many of you requested steps for current release of JBoss 4.2.2 GA, here it goes:

* deploy/jboss-web.deployer/server.xml
o change 8080 to 18080
o change 8443 to 18443
o change 8009 to 18009
* deploy/http-invoker.sar/META-INF/jboss-service.xml
o change 8080 to 18080
* deploy/jbossws.sar/jbossws.beans/META-INF/jboss-beans.xml
o change 8080 to 18080
o change 8443 to 18443
* deploy/ejb3.deployer/META-INF/jboss-service.xml
o change 3873 to 13873
* deploy/jms/uil2-service.xml
o change 8093 to 18093
* conf/jboss-service.xml
o change 8083 to 18083
* conf/jboss-minimal.xml
o change 1099 to 11099
o change 1098 to 11098
* conf/jboss-service.xml
o change 1099 to 11099
o change 1098 to 11098
o change 4444 to 14444
o change 4445 to 14445
o change 4446 to 14446

There can be many entries of these port numbers in these files. Make sure you change all of them.

Developing RESTful Web Services in Java

July 18th, 2006

When you think of Web services, SOAP immediately comes to your mind. Not any more! Thanks to REST, there is a simpler way to develop web services. While SOAP is well established with most vendors supporting it, REST is really catching up.

Representational State Transfer (REST) is an architectural style for distributed hypermedia systems. REST relies on a single application protocol (HTTP), universal resource indicators (URI) and standardized data formats, through XML. It employs established HTTP methods such as GET and POST to direct applications.

I’m not attempting to explain the concept of REST, there are already enough stuff all over the Internet. You may have noticed that most of the Internet giants offer their services as REST web services. They may be good APIs but not RESTful.

What is not REST?

* APIs that involve Plain Old XML over HTTP are not necessarily REST.

* Using GET for all operations – including insert, updates etc is not REST

Creating a new Person resource:
GET myhost/api?action=create&item=person&name=mano Incorrect
POST myhost/api/person
name=mano Correct

* Not having distinct URI for first class objects is also a violation of the REST way.

Retrieving a Person resource
GET myhost/api?item=person&id=202 Incorrect
GET myhost/api/person/202 Correct

A RESTful service has use http methods such as POST, GET, PUT and DELETE to achieve the basic CRUD operations (create, read, update, and delete). All resources are identified using distinct URIs.

Framework in Java

I found Restlet to be a good framework. Restlet ensures that your application can easily be developed in a RESTful manner. Each concept of REST has a corresponding Java interface or class in the Restlet API. Another advantage is the ability to work with multiple protocols (HTTP, JDBC, SMTP, etc.) using the exact same API.

However, I could not find a good example for restlet + spring + tomcat integration, I took the liberty of writing one. You can download the restdemo application here. Just run ant, drop the WAR in your webapps folder – you are all set.

Download RestDemo ZIP

Our Dream House

June 30th, 2006

houseWe just became proud owners of our dream house. The house is 2-storied with 4 bedrooms, has a welcoming front yard, a huge private backyard, great schools and a lovely community. We are all quite excited about this.I hope to publish more pictures and videos of the house in near future.

Niagara Falls Trip

April 21st, 2006

We had a great vacation at Niagara Falls and drove more than 1200 miles with Arvind. We crossed the American border and spent the next couple of days at Niagara Falls, Canada.The weather was quite pleasant in the lower 50s. The hotel stay was nice and from our room we could view and enjoy the falls.

We visited ‘Kingdom of Lost Birds’ – the largest indoor aviary in the world. Arvind had lot of fun chasing all pretty colored birds. We spent long hours at the Falls, walked a lot, took the boat ride, enjoyed the night illumination from the Skylon tower. Niagara is awesome!!

We also had time to visit other places of interests – Wax museum, Guiness world records museum, Ripley’s Believe it or not.

Enjoy pictures and video.

Short Home Videos

April 13th, 2006

The last two home videos that I created were about an hour long. While a lot shooting is required to make such movies, the effort and time required is even more significant. For a change, I’m going to create very short movies (clippping) and make then available on the internet through my site. This way, I would be able to share these immediately with my friends and family. Check out the Home Video section. I have added Arvind’s petfarm visit to it.

Better jUnit-ing

April 2nd, 2006

jUnit has been around for a long time. But there are always better techniques to implement old ways. I have provided below an efficient junit aprroach integrated with DbUnit and Spring with support for transaction and hibernate open session. Significant features are:

* Integration with DbUnit: DbUnit puts database into a known state between test runs. Pre-loads database with known data set before the test
* Transaction support using spring: After each test all changes made by the test are rolled back. Hence there is no need to programatically undo channges made by the test. Much cleaner code. (Thanks, Jim)
* After each test, clear the pre-loaded data set from database
* Support for open session in view: Web applications using Hibernate with lazy loading need to keep the session open till the view is rendered. (Read more)

/**
* Junit test integrated with DbUnit and spring. Provides support for
* transaction and open session. This wraps each test method with a
* transaction and rollbacks after the method exits. DbUnit
* is used to load up the table with initial set of values.
*/

public class MyTest extends AbstractTransactionalDataSourceSpringContextTests {

private SessionFactory sessionFactory;
private Session session;
private static ConfigurableApplicationContext factory;
private final String[] TABLES = { “EmployeeTable”, “DepartmentTable” };
private final String DATA_FILE = “data.xml”;
private final String[] CONFIG_LOCATIONS = { “spring-context.xml” };

public static Test suite() {
return new TestSuite(MyTest.class);
}

protected String[] getConfigLocations() {
return CONFIG_LOCATIONS;
}

// This method is used to perform any setup operations, such as
// populating a database table, within the transaction.
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
if (factory == null) {
factory = new ClassPathXmlApplicationContext(getConfigLocations());
}
// Load test data using DBUnit
DataSource ds = (DataSource) factory.getBean(”dataSource”);
Connection con = DataSourceUtils.getConnection(ds);
IDatabaseConnection dbUnitCon = new DatabaseConnection(con);
IDataSet dataSet = new FlatXmlDataSet(Thread.currentThread().
getContextClassLoader().getResourceAsStream(DATA_FILE));
try {
DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dataSet);
} finally {
DataSourceUtils.releaseConnection(con, ds);
}
// Support of open session
sessionFactory = (SessionFactory) factory.getBean(”sessionFactory”);
session = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}

protected void onTearDownAfterTransaction() throws Exception {
// delete table entries
deleteFromTables(TABLES);
// release session
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
session = holder.getSession();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.releaseSession(session, sessionFactory);
}

public void testSomething() throws Exception {
// …
}

}

Access denied error in MySQL

March 31st, 2006

Have you been frustrated with Access denied for user ‘chinnu’@’localhost’ errors even though as root you granted following privileges:

GRANT ALL PRIVILEGES ON MyDb.* to ‘chinnu’@'%’ WITH GRANT OPTION;

While % means any host, you probably did not see the behavior you expected.

MySQL performs access control in two stages. First, it tries to connect you with the username/password provided. Next, it checks if you have the privileges to perform your request. Entries in tables user, db and host of mysql database are used for access control.

Lets say this is our user table:

——————–
Host | User
——————–
% | root
% | chinnu
localhost | root
localhost |
——————-

% in Host means ‘any host’ and blank in User means any user or anonymous user. Note that the value % is less specific when compared to value localhost. MySQL, when performing access control, sorts this table with the most-specific Host at the top. So, we have something like

——————–
Host | User
——————–
localhost | root
localhost |
% | chinnu
% | root
——————-

When chinnu tries to login from localhost, there are two matching rows. Guess what, the first match wins. This means that chinnu is effectively logged in as an anonymous user. The anonymous user may not have privileges for MyDb, hence the access denied errors.

How to verify?
If you managed to connect execute SELECT CURRENT_USER(). If you get result as @localhost and not chinnu@localhost, you have the issue described above.

How to solve this?
Solution-1: Grant privileges for ‘chinnu’@’localhost’ in addition to ‘chinnu’@’%’
Solution-2: Just get rid of the anonymous user

Radha’s India Visit

February 21st, 2006

Radha and Arvind returned back from India last week.

They had busy 4-week trip visiting friends and family members. They first landed at Chennai and drive to Velachery where Mano’s parents live. After few days, flew to Ahmedabad to visit her sister. Back to Chennai and spent time with her other sister. Then, they took the train to Srirangam to visit Radha’s parents. They also paid visit to temples. They came back to Chennai, packed their stuff and flew to US.

Arvind enjoyed the trip very much. It took about a week for him to overcome the jet lag and the time differential. He was cheerful, active. He had lot of fun playing with his cousins. All objectives of the trip achieved:

* Have fun
* Visit everybody
* Buy/get things planned
* Don’t fall sick