Friday, August 6, 2010

Combine local Git branches with central Subversion repository

Assuming you already heard of Git as SCM alternative for Subversion, you might also know that it includes some integration with Subversion. That provides you the option to start using some Git advantages in your daily work without worrying your local operations department, possibly in a very stealthy way.

After using the gateway for a few months, I discovered and started using another nice Git feature: easy merging and working with a separate development branch. Problem was that we usually have some debug settings enabled in some of the project files, resulting into some kind of "development" build, instead of a "production" build of the program. It is possible to fix this with some extra build configuration parameters outside the project, but using Git offers you another easy solution: just locally fork the code with your own settings.

The "master" branch contains the production code, and the "dvl" branch my modified version. Once the customization is checked into the "dvl" branch, you can synchronize ("pull") the "master" branch based on "dvl" and undo the customization. Now switch back to your development branch is just keep work like you used to do previously. Any moment you can check your workspace using "git status" and your custom patch won't bother you. It also prevents you to push the development setting to the central Subversion repository by accident with the commit all command ("git commit -a").

But how do I push the wanted (!) code changes to our central repository when I'm ready? Well, by injecting one extra step, before directly pushing code from "master" to Subversion: rebase "master" on "dvl" branch. This involves a little extra administration, so the following little shell script fragment helps me out to save typing work:


# move to master branch
git checkout master

# pull changes from dvl and re-apply patch on top
git rebase dvl

# required 2 steps because dcommit would complain about sync
git svn fetch
git svn rebase

# push changes to central SVN repo
git svn dcommit

# switch back to dvl branch
git checkout dvl


One of the drawbacks of this system, is the visibility of the patch and undo steps in the history from the master branch, also propagated to the central Subversion. Maybe history rewriting fixes this, or I could implement some some other workflow, but for the moment I'm not really troubled about that. If anyone as a better alternative, I'd be happy to learn!

Some good links:

Tuesday, October 6, 2009

Subversive not supporting rename/move in workspace

One of the nice features of Subversion over CVS, is the the support for resource renaming. It provides you the opportunity to easily follow the history of a file, even if it has been renamed of moved around your directory structure.

Too bad that the Subversive plugin for Eclipse has some problems with supporting this feature, and there seems to be no easy fix. The command line Subversion client works fine, but what if we want to stay in our comfortable, fancy IDE?

https://bugs.eclipse.org/bugs/show_bug.cgi?id=213991

The Subversion rename is actually a copy together with a delete. So, the workaround in Subversive: open the context menu of your file, select "Team", "Copy To .." and input the new destination, while keeping your history. Next step is to delete the file on the original location. If you check the history of the "new" file, Subversive won't show you any remote revision information. Don't be afraid, it will re-occur once you have committed your changes.

On the other hand, the SVN Repositories view supports moving files around directly on the repository. This is fine if you don't need to change file internally or any other file in the same commit. But if your move some Java source file, you probably need to update some import references and package definitions as well. So you want to apply these changes in your workspace first, and commit all changes together, instead of having a inconsistent (temporary) state at the repository.

Now you know this, take up the challenge and fix the bug in Subversive! ;-)

Tuesday, August 5, 2008

Performance monitoring web applications with JavaScript

As end users, we often complain about slow web applications, and the same complaint is fired by the user towards us as web application developer. Most used monitoring solutions are based on some request filter implementation, where the server logs the timestamps of the incoming request and outgoing response. This works fine and provides good insight how much time we spend at the application server.

But how do we monitor the delay between the browser and the server, consisting out many multiple firewalls, proxies and many other slow network nodes? Especially when the browser machine is connected to internet directly, without some kind of corporate LAN where you could introduce a monitoring proxy?

After a bit of brainstorming with a smart colleague (thanks Marc), I found a very simple solution based on JavaScript. It catches browser navigation events using the load and unload events and stores the timestamps in a HTTP cookie variable. It does NOT work for asynchronous AJAX events, nor for separately loaded images, but it works well enough for us.


function enterPage() {
var endTime = new Date().getTime()
var timeIndex = document.cookie.indexOf("exitTime=")
var endPoint = document.cookie.indexOf(";", timeIndex)
var startTime = document.cookie.substring(timeIndex + 9, endPoint)
var duration = endTime - startTime
document.cookie = "duration=" + duration + ";"
}

function exitPage() {
var startTime = new Date().getTime()
document.cookie = "exitTime=" + startTime + ";"
}

<body onload="enterPage()" onunload="exitPage()">
my example page
</body>


The browser stores the load duration time in a cookie after the new page is rendered, and posts the cookie to the server in next HTTP request. Since we use J2EE at the server, we simply use the HttpServletRequest.getCookies() method to extract the value.

HTML events
JavaScript and Cookies

Thursday, July 10, 2008

Using dependency injection in EJB2

Many J2EE developers are still facing legacy projects, often containing horrible EJB2 session beans. Once I understood the improvements of EJB3 and the Spring alternatives for dependency injection, I cursed the ugly dependency look code in old EJB2 code.

Even if you cannot switch to an EJB3, you can still improve your existing code.
This is a sample of a typical EJB2 bean:


public class BookingBean implements SessionBean {
private CustomerDAO customerDAO;
private HotelDAO hotelDAO;
public void ejbCreate() {
customerDAO = Locator.lookup(CustomerDAO.class);
hotelDAO = Locator.lookup(HotelDAO.class)
}
}


If you have a lot of session beans, based on top of a large set of DAO instances, all this becomes a maintenance nightmare. It is very obvious that the code in the ejbCreate() method is really superfluous.

What I want to achieve in the new version:


public class BookingBean implements SessionBean {
@Autowired private CustomerDAO customerDAO;
@Autowired private HotelDAO hotelDAO;
public void ejbCreate() {
// use automatic injection of instances from global context
}
}


The "global context" can be something like a Spring application context, a classic JNDI naming context, or anything you want. Using reflection and a little bit of generic code, you can move the ejbCreate() to a base class.

Remaining work to do to wire a session bean to the dependencies:

  1. extend from the correct base class

  2. annotate your dependencies



Related links:

Tuesday, September 11, 2007

Container Managed Transactions in EJB

Be careful when using more "advanced" transaction configurations in EJB. Yesterday, we spent quite some time investigating the reason why calling a bean method marked with the RequiresNew TX attribute, did NOT spawn a separate TX context.


class SomeSessionBean implements SomeSession {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void helperMethod() {
// must perform some update in separate TX
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void mainMethod() {
this.helperMethod();
}
}


The code flows into mainMethod(), and that was expected to perform helperMethod() in another transaction. A simple test case and a debugging run clearly showed that only the original transaction was used in the entire flow.

What happened? The container does NOT intercept the second method invocation, so it cannot create a new transaction. One way to solve it, is doing some JNDI lookup (EJB2) or performing a EJB injection (EJB3). Both workaround will work as intended, but have one drawback: pollution of the original API with implementation "details".

IMHO the better solution: define a separate helper bean containing the helper methods. It requires some framework code in EJB2, but when you are "blessed" by EJB3, it can provide you a rather elegant solution, where the front session bean, delegates logic within a separate TX to another bean.

In case you need much more complexity, it may be better to use bean managed transactions, but I recommend to try this first. The bottom line: keep a close watch on transaction attributes of EJB session beans, and be aware of the existence, or the opposite, of the surrounding container!

Thursday, June 7, 2007

Oracle support for hierarchical queries

Most of us already encountered the problem of walking through a tree-like structure in database table. Imagine a PERSON table with parent-child relationship, and we want to retrieve all descendants of a person quickly. In plain JDBC and standard SQL, you'll need to write yourself a recursive function and perform multiple requests on your favorite database. Good news for users of Oracle 10g databases: Oracle SQL has extensions to fetch all descendants in one single query! You just need to use the START WITH and CONNECT BY keywords. Have a quick look at this Oracle article for more details.

Thanks to ITwise and DbMotive for the great tip!

Thursday, May 24, 2007

Character encoding matters in Java

Last week, a co-worker told me he was breaking his head since several days about one special character in an XML file. The programming project had to migrate from a Microsoft Windows to GNU/Linux platform, and a few automatic tests keep failing. In the end, it all came down to one single "e" character with a diaeresis. The character was read correctly on Windows, but the same test file results into an unexpected character on Linux side.

What is the problem?


On most Microsoft platforms, there is encoding character set (CP1252) available for the main languages in Western Europe. Beside the Microsoft mapping, there is also an international standard ISO-8859-1 (also known as LATIN-1), supported on almost every system.

What most developers forget when performing character I/O operations in Java, is thinking about encoding. As long as you stay on a single platform, and always work with files encoded with the same schema, that works fine. Problems occur when you migrate to another platform, or have to deal with text files in alternate encodings. In this particular example, the XML file was encoded in (default) CP1252. On the Linux side however, the default encoding schema is ISO-8859-1, and the same text file is interpreted differently. This results into unexpected text read from files.

Find a solution


How to solve this? Use a common encoding like ISO-8859-1. Or even better, UTF-8 from the Unicode standard. The latter one adds support for almost every language in the world, and is well supported in lot of platforms. Next step is to implement in both the write and read code. If you look into the InputStreamReader and OutputStreamWriter documentation from the java.io package, you'll easily find they support custom encoding schemes. An alternate way is to specify the encoding on Java VM startup, with the file.encoding environment variable.

Some extra catches


  • UTF-8 is a superset of US-ASCII, but NOT of LATIN-1

  • use the same encoding for the DTD/XSD, not only the actual XML file

  • some Microsoft text editors, add an extra, non-standard BOM prefix in Unicode documents

  • CVS clients may strip or add carriage return and/or newline characters, but usually this is no problem in XML documents



Useful links

* ISO-8859-1 at wikipedia
* UTF-8 at wikipedia