I've seen very few developers using true power of Eclipse editors, so I thought of listing few very handy shortcuts that can significantly improve your source editing and navigation speed with Eclipse.
1. Ctrl + J / Ctrl + Shift + J : Inline search, meaning you can type on the fly to search text in current editor. You can use Up/Down arrow keys to navigate between matching text fragment in forward/reverse direction. This is one of the most powerful features you will find in advanced editors like Vim or Emacs.
2. Ctrl + K/ Ctrl + Shift + K : Search text in forward or reverse direction.
3. Ctrl + L : Go to line.
4. Ctrl + Alt + Up/Down : Duplicate current line above/below. Very useful in repeatative assignment statements (Java code, eh?).
5. Alt + Up/Down : Move current line up or down. Also, very handy to select current line.
6. Ctrl + . OR , : This is contextual and may be specific to Java editors: if you have error or warnings in current file in editor it will navigate to them.
All of these except for no. 6 are generic text editor features which are inherited by all eclipse text editors. You will realize that you will work much faster than average user if you start using these key bindings.
Saturday, August 16, 2008
Wednesday, August 06, 2008
Synchronizing client requests using Ajax
Before few months I was dealing with a problem where I needed to synchronize the server call sequence on browser. The problem was something like this: Client code will open new window navigating to a different page, but that should happen only after post on current page. The link that new window was opening needed to be server synchronized because of database updates etc. on server.
Being ignorant java-script developer I went ahead and put 'window.open' in onsubmit event of submit button, hoping it will be executed before form is submitted; Apparently, it failed. The event handling/dispatching/capturing in java-script is in sad state - it's specific to browser and I must make it work for IE so the pain is obvious. To reveal some more ignorance, I thought of putting 'window.open' in onmousedown event assuming form will not be submitted till the code in onmousedown is executed
fully, that too failed. Then, it was clear that 'window.open' was essentially a thread fork and will execute in parallel so this event capturing is not going to work here.
Since there was no obvious fix to my problem, I thought of using XMLHTTP for asynchronous wait to synchronize the request. I created new page which will open in a new window with javascript that handles form post in parent window, looks like following:
Being ignorant java-script developer I went ahead and put 'window.open' in onsubmit event of submit button, hoping it will be executed before form is submitted; Apparently, it failed. The event handling/dispatching/capturing in java-script is in sad state - it's specific to browser and I must make it work for IE so the pain is obvious. To reveal some more ignorance, I thought of putting 'window.open' in onmousedown event assuming form will not be submitted till the code in onmousedown is executed
fully, that too failed. Then, it was clear that 'window.open' was essentially a thread fork and will execute in parallel so this event capturing is not going to work here.
Since there was no obvious fix to my problem, I thought of using XMLHTTP for asynchronous wait to synchronize the request. I created new page which will open in a new window with javascript that handles form post in parent window, looks like following:
getFormValues is a function which concatenates all the input's selected values and makes a request string. More interesting things are done in makePOSTRequest method:<html>
<body onload="postParentWindow()">
<%
out.print("Loading Print Preview, Please wait...");
%>
</body>
</html>function postParentWindow(){
url = window.opener.document.forms['form'].action
params = getFormInputValues(window.opener.document.forms['form']) + "&form:Submit=Save Page";
makePOSTRequest(url, params);
}
(Note: This code completely disregards browser compatibility and good error handling etc.) The important thing here is, we can assign a function to XMLHTTP object that will be executed after server response is received so that serves my purpose of synchronizing the request. I find this use of AJAX pretty useful in building stateful web-applications. The code might look very crude but powerful abstractions can be built over it to make a nice utility framework for such use-cases.var http_request = false;
function makePOSTRequest(url, parameters) {
http_request = false;
try {
http_request = newActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
http_request.onreadystatechange = navigateToOtherPage;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
function navigateToOtherPage() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
window.navigate('newpage.jsf');
} else {
alert('There was a problem with the request.');
}
}
Tuesday, August 05, 2008
What's wrong with HP Quality Center?
This entry is rant so you might just want to skip it.
HP Quality Center (formerly Mercury) is a, how so amusingly called, web-based test management tool. You will find a lot of marketing information if you ask Google, most of which is irrelevant and may only have 1-800 number for support; because they know when you are looking for it on web, you are in trouble and no one can help you. Unfortunately, I've to spend a good amount of time on this tool these days and it inspired me a great deal to write my inexpressible ovation for this tool here.
As a programmer, HP Quality center is one of the worst and most annoying tools you may have to work with (some may compare it with Lotus notes though).
This tool is implemented as a giant Active X; Apparently, they didn't want to make it web-based but when sales team threatened their developers, they some how adjusted their extra-thick client to web by (evil) means of Active-X(TM) technology. It only takes one or two more minutes to load than my Eclipse instance does, in Intra-net i.e.. It works only on lame Internet Explorer, in a sense that makes it 70% less web based. To add to the insult of using this tool, you have no option but use god-forsaken IE6 (or 7 if you are slightly lucky).
HP Quality center crashes at will, each crash is designed scientifically so that you waste a few hours to get back to normal work before it crashes again. For example, I add attachment to a defect; next, I go and try to add comment on it and it crashes - right on time. I open new IE window; browse it and wait for it to load, log-in again (this special web based tool doesn't have feature to remember your password in an enterprise-wide SSO environment). After recalling what I was doing last, I go to the defect where it crashed and try to add comment again; only to discover that it still thinks I'm working on it. 'The object is locked by user: [my userid]'. You will praise arcane brilliance imbued in this tool because these problems disappears randomly once it pisses you off - it knows when.
Some more praise on it's resource utilization, so one can't wonder why it is rightfully web-based. HP Quality Center uses ~120mb of your core if you have no defects in your view. This amazing tool can make your wish to see memory usage on crack come true, have 50-40 defects in your view and see the difference.
This is only the tip of the iceberg but gives you bigger picture and idea why companies make more money in support, there's always room for new version, patch, hotfix etc. Why in the world people pay for such crap? there are ton of free alternatives which are hundred times better and are totally free. And the other day someone was complaining about open-source tool usability...
HP Quality Center (formerly Mercury) is a, how so amusingly called, web-based test management tool. You will find a lot of marketing information if you ask Google, most of which is irrelevant and may only have 1-800 number for support; because they know when you are looking for it on web, you are in trouble and no one can help you. Unfortunately, I've to spend a good amount of time on this tool these days and it inspired me a great deal to write my inexpressible ovation for this tool here.
As a programmer, HP Quality center is one of the worst and most annoying tools you may have to work with (some may compare it with Lotus notes though).
This tool is implemented as a giant Active X; Apparently, they didn't want to make it web-based but when sales team threatened their developers, they some how adjusted their extra-thick client to web by (evil) means of Active-X(TM) technology. It only takes one or two more minutes to load than my Eclipse instance does, in Intra-net i.e.. It works only on lame Internet Explorer, in a sense that makes it 70% less web based. To add to the insult of using this tool, you have no option but use god-forsaken IE6 (or 7 if you are slightly lucky).
HP Quality center crashes at will, each crash is designed scientifically so that you waste a few hours to get back to normal work before it crashes again. For example, I add attachment to a defect; next, I go and try to add comment on it and it crashes - right on time. I open new IE window; browse it and wait for it to load, log-in again (this special web based tool doesn't have feature to remember your password in an enterprise-wide SSO environment). After recalling what I was doing last, I go to the defect where it crashed and try to add comment again; only to discover that it still thinks I'm working on it. 'The object is locked by user: [my userid]'. You will praise arcane brilliance imbued in this tool because these problems disappears randomly once it pisses you off - it knows when.
Some more praise on it's resource utilization, so one can't wonder why it is rightfully web-based. HP Quality Center uses ~120mb of your core if you have no defects in your view. This amazing tool can make your wish to see memory usage on crack come true, have 50-40 defects in your view and see the difference.
This is only the tip of the iceberg but gives you bigger picture and idea why companies make more money in support, there's always room for new version, patch, hotfix etc. Why in the world people pay for such crap? there are ton of free alternatives which are hundred times better and are totally free. And the other day someone was complaining about open-source tool usability...
Thursday, April 24, 2008
How to: Always eagerly load objects from database with Hibernate 3 (without changing configuration xmls)
So it was getting annoying to debug my app. with Hibernate 3 for it's 'lazy load everything by default' feature. Every time I wanted to see what's the value of some collection I will see these weird CGLIB proxy members lurking in debug views.
So before it becomes nightmare for me I thought of hacking hibernate to make it eagerly load entire object from database. I'm saying hacking because there's no API in Session or SessionFactory interfaces that would allow you to unwrap these un-dead proxies automatically.
Here's how you can hack hibernate to prevent lazy loading:
The basic idea of making hibernate do what you want is to invert it's assumption, i.e. make everything load eager by default, we'll plug ourself to Mappings class and will force eager load implicitely. Follow these steps:
1. First create a class in org.hibernate.cfg package which extends Mappings:
The 'addClass' method achieves all we need, just make persistenceClass non-lazy, it would be lazy by default.
2. Now hook this class with Configuration class.
This was way easier to achieve than I could think hooking hairy SessionImpl beast and making org.hibernate.event.LoadEventListener.LoadType INTERNAL_LOAD_EAGER from INTERNAL_LOAD_LAZY without changing SessionImpl itself.
Other than that, I found some talking about lazy loading being problematic with XStream serialization. Threre's a JIRA defect for XStream relating to this as well. I faced the same few weeks before when I thought of removing hibernate from test cases, XStream basically throws up when it finds a confusing CGLIB proxy like this:
CGLIB$CALLBACK_0 org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer@9be3aaFor every association I would either evaluate the code or create expressions to see what's coming from DB. Lazy loading makes debugging more slower than it already is. What's the big deal?, you will say, Just go ahead and change configuration to lazy-load = "false". Well, I can do it but changing more than five hundred .hbm.xml files will help me more with retiring early than fixing the problem at hand.
class$net$sf$cglib$proxy$InvocationHandler interface net.sf.cglib.proxy.InvocationHandler
class$net$sf$cglib$proxy$NoOp interface net.sf.cglib.proxy.NoOp
class$org$hibernate$proxy$pojo$BasicLazyInitializer null
componentIdType null
constructed true
So before it becomes nightmare for me I thought of hacking hibernate to make it eagerly load entire object from database. I'm saying hacking because there's no API in Session or SessionFactory interfaces that would allow you to unwrap these un-dead proxies automatically.
Here's how you can hack hibernate to prevent lazy loading:
The basic idea of making hibernate do what you want is to invert it's assumption, i.e. make everything load eager by default, we'll plug ourself to Mappings class and will force eager load implicitely. Follow these steps:
1. First create a class in org.hibernate.cfg package which extends Mappings:
package org.hibernate.cfg;
import java.util.List;
import java.util.Map;
import org.hibernate.MappingException;
import org.hibernate.mapping.PersistentClass;
public class MyMapping extends Mappings {
public MyMapping(Map classes, Map collections, Map tables, Map queries, Map sqlqueries, Map sqlResultSetMappings,
Map imports, List secondPasses, List propertyReferences, NamingStrategy namingStrategy,
Map typeDefs, Map filterDefinitions, Map extendsQueue, List auxiliaryDatabaseObjects,
Map tableNamebinding, Map columnNameBindingPerTable) {
super(classes, collections, tables, queries, sqlqueries, sqlResultSetMappings, imports, secondPasses,
propertyReferences, namingStrategy, typeDefs, filterDefinitions, extendsQueue, auxiliaryDatabaseObjects,
tableNamebinding, columnNameBindingPerTable);
}
@Override
public void addClass(PersistentClass persistentClass) throws MappingException {
persistentClass.setLazy(false); // No Proxies, load everything in one shot
super.addClass(persistentClass);
}
}
The 'addClass' method achieves all we need, just make persistenceClass non-lazy, it would be lazy by default.
2. Now hook this class with Configuration class.
public class MyConfiguration extends Configuration {There you go, You can now create session factory out of it and you will get fully debug-compatible Java objects loaded from db.
@Override
public Mappings createMappings() {
return new MyMapping(classes, collections, tables, namedQueries, namedSqlQueries, sqlResultSetMappings,
imports, secondPasses, propertyReferences, namingStrategy, typeDefs,
filterDefinitions, extendsQueue, auxiliaryDatabaseObjects, tableNameBinding,
columnNameBindingPerTable);
}
}
This was way easier to achieve than I could think hooking hairy SessionImpl beast and making org.hibernate.event.LoadEventListener.LoadType INTERNAL_LOAD_EAGER from INTERNAL_LOAD_LAZY without changing SessionImpl itself.
Other than that, I found some talking about lazy loading being problematic with XStream serialization. Threre's a JIRA defect for XStream relating to this as well. I faced the same few weeks before when I thought of removing hibernate from test cases, XStream basically throws up when it finds a confusing CGLIB proxy like this:
com.thoughtworks.xstream.converters.ConversionException: Cannot handle CGLIB enhanced proxies with multiple callbacksI faced this problem before as well and now I don't have to worry about it anymore. You guys can probably just go ahead and load your objects as I described above and your serialization would work fine.
at com.thoughtworks.xstream.converters.reflection.CGLIBEnhancedConverter.marshal(CGLIBEnhancedConverter.java:85)
at com.thoughtworks.xstream.core.AbstractReferenceMarshaller.convert(AbstractReferenceMarshaller.java:55)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:50)
at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:73)
at com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy.marshal(ReferenceByXPathMarshallingStrategy.java:34)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:765)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:754)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:735)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:725)
Subscribe to:
Posts (Atom)