DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

The Latest Java Topics

article thumbnail
Commons Lang 3 -- Improved and Powerful StringEscapeUtils
In the first and second parts of this series I talked about some of the new features like enum and concurrency support that have been added in commons-lang 3. In this article, I am going to talk about a new package 'org.apache.commons.lang3.text.translate' which has been added in commons-lang 3. This package is added to fix problems in the design and implementation of the StringEscapeUtils class which exists in versions prior to 3.0. To make it clearer, let's first talk about the purpose of StringEscapeUtils class and the problems it had prior to version 3. Purpose of StringEscapeUtils StringEscapeUtils is a utility class which escapes and unescapes String for Java, JavaScript, HTML, XML, and SQL. For example, @Test public void test_StringEscapeUtils() { assertEquals("\\\\\\n\\t\\r", StringEscapeUtils.escapeJava("\\\n\t\r")); // escapes the Java String assertEquals("\\\n\t\r",StringEscapeUtils.unescapeJava("\\\\\\n\\t\\r")); //unescapes the Java String assertEquals("I didn\\'t say \\\"you to run!\\\"",StringEscapeUtils.escapeJavaScript("I didn't say \"you to run!\""));//escapes the Javascript assertEquals("<xml>", StringEscapeUtils.escapeXml(""));//escapes the xml } Problems with StringEscapeUtils There were a lot of problems in the StringEscapeUtils implementation prior to version3. Some of these were: The implementation was not extensible. Let's take an example of escapeJava, suppose we want to add support in the escapeJava method that it should start escaping single quotes. To add such support we would have to change the existing class code and another if condition which if satisfied will escape single quotes. So, the API was breaking the open-closed principle i.e. a class should be open for extension and closed for modification. It was not symmetric i.e. original should be equal to unescape(escape(original)) but it was not the case. StringEscapeUtils.escapeHtml() escapes multibyte characters like Chinese, Japanese etc. Issue 339 @Test public void testEscapeHiragana() { // Some random Japanese unicode characters String original = "\u304B\u304C\u3068"; String escaped = StringEscapeUtils.escapeHtml(original); assertEquals(original, escaped); } StringEscapeUtils.escapeHtml incorrectly converts unicode characters above U+00FFFF into 2 characters. Issue 480 @Test public void testEscapeHtmlHighUnicode() throws java.io.UnsupportedEncodingException { byte[] data = new byte[] { (byte) 0xF0, (byte) 0x9D, (byte) 0x8D,(byte) 0xA2 }; String original = new String(data, "UTF8"); String escaped = StringEscapeUtils.escapeHtml(original); assertEquals(original, escaped); } StringEscaper.escapeXml() escapes characters > 0x7f . Issue 66 @Test public void shouldNotEscapeValuesGreaterThan0x7f() { assertEquals("XML should not escape >0x7f values", "\u00A1",StringEscapeUtils.escapeXml("\u00A1")); } Solution -- Rewritten StringEscapeUtils In version 3.0, StringEscapeUtils is completely rewritten to fix all the bugs associated with this class and to provide a way for the user to customize the behavior of its methods. They have moved all the logic present in the StringEscapeUtils to the classes in the package 'org.apache.commons.lang3.text.translate'. Let's take an example of escapeJava function in StringEscapeUtils, escapeJava function does not contain any business logic, it just calls the translate method on CharSequenceTranslator reference. What they did can be best understood by looking at the code below public static final CharSequenceTranslator ESCAPE_JAVA = new AggregateTranslator(new LookupTranslator( new String[][] { {"\"", "\\\""}, {"\\", "\\\\"}, }),new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()),UnicodeEscaper.outsideOf(32, 0x7f)); and in the escapeJava method public static final String escapeJava(String input) { return ESCAPE_JAVA.translate(input); } A constant of type CharSequenceTranslator was assigned an AggregateTranslator object. AggregateTranslator can take an array of translators, and it iterates over each of them. The LookupTranslator replaces the string at zeroth index with the string at the first index. UnicodeEscaper translates values outside the given range to unicode values. As you can see, you can very easily write your own escape methods. For example, if you want to add the support of escaping &, you can do it like this public static final CharSequenceTranslator ESCAPE_JAVA = new LookupTranslator( new String[][] { {"\"", "\\\""}, {"\\", "\\\\"}, }).with(new LookupTranslator( new String[][]{ {"&", "&"}, {"<", "<"} )).with( new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()) ).with( UnicodeEscaper.outsideOf(32, 0x7f) ); StringEscapeUtils.escapeSql has been removed from the API as it was misleading developers to not use PreparedStatement.This method was not of much use as it was only escaping single quotes.
September 17, 2010
by Shekhar Gulati
· 71,234 Views · 2 Likes
article thumbnail
Exposing a POJO as a JMX MBean Easily With Spring
JMX is a great way to check or change state variables or invoke a method in a (remote) running application via a management GUI such as JConsole. And Spring makes it trivial to expose any POJO as a JMX MBean with only little configuration in a few minutes. The Spring JMX documentation is very good, however there are few points that I struggled with for a while and would therefore like to record here the right solutions. I needed to monitor a command-line java application using Spring 2.5 on IBM JVM 1.4 1.5 running on a server with a jconsole on Sun JVM 1.6 as the JMX client on my PC. All the XML snippets are from a Spring application-context.xml. If you haven’t used Spring before, read a tutorial on its configuration and dependency injection. Turning a POJO into an MBean JMX makes it possible to expose getters, setters and operations taking primitive or complex data types as parameters (though types other then few special ones require the client to have the classes). You tell Spring to expose a POJO as an MBean as follows: First you declare an instance of the POJO class – the myMBean (for other reasons I’ve an old-fashioned singleton and use JobPerformanceStats.instance() to access the bean). Next you declare an MBeanExporter with lazy-init=”false” and tell it about your bean. (There are also other ways to do it, including auto-discovery.) The bean will be then visible under its key, i.e. “bean:name=MyMBeanName”, which JConsole displays as “MyMBeanName”. Notice that the MBeanExporter only works under JVM 1.5+ because it uses the new java.lang.management package. Under 1.4 Spring would fail with java.lang.NoClassDefFoundError: javax/management/MBeanServerFactory at org.springframework.jmx.support.MBeanServerFactoryBean.createMBeanServer By default it will expose all public methods and attributes. You can change that in various ways, for example with the help of an interface. If you are not running in a container that already provides an MBean server, which is my case here, you must tell Spring to start one: Enabling remote access To make the MBean accessible from another machine, you must expose it to the world by declaring a ConnectorServerFactoryBean configured with an appropriate communication mechanism. Remote access over JMXMP By default the ConnectorServerFactoryBean exposes MBeans over JMXMP with the address service:jmx:jmxmp://localhost:9875 : However this protocol isn’t supported out of the box and you must include jmxremote_optional.jar, a part of OpenDMK, on the classpath of both the MBean application and the jconsole client to avoid the exception org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.jmx.support.ConnectorServerFactoryBean#0′ defined in class path resource [application-context.xml]: Invocation of init method failed; nested exception is java.net.MalformedURLException: Unsupported protocol: jmxmp Remote access over RMI Alternatively you can expose the MBeans over RMI, which has no additional dependencies: However there are also some catches you must avoid: You must start an RMI registry so that the connector can register the MBean there; it won’t start one for you You must make sure that the registry is started before the connector tries to use either by declaring it before the connector or by making this dependency explicit with the depends-on attribute If you don’t set it up correctly you will get an exception like org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘org.springframework.jmx.support.ConnectorServerFactoryBean#0′ defined in class path resource [application-context.xml]: Invocation of init method failed; nested exception is java.io.IOException: Cannot bind to URL [rmi://localhost:10099/jmxrmi]: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: localhost; nested exception is: java.net.ConnectException: Connection refused: connect]. Local MBean server accessed over an SSH tunnel For increased security you may want to prefer not to expose your MBeans to remote access by making them accessible only from the local machine (127.0.0.1) and use na SSH tunnel so that a remote JConsole can access them as a local application. This is certainly possible but may be difficult because normally JMX goes over RMI, which uses two ports: one for the RMI Registry and another one for the actual service (MBean server here), which is usually chosen randomly at the runtime, and you’d need to tunnel both. Fortunately, Spring makes it possible to configure both the ports: Replace STUBPORT and REGISTRYPORT with suitable numbers and tunnel those two. Notice that the REGISTRYPORT number is same in the connector’s serviceUrl and in the RMI registry’s port attribute. WARNING: The configuration above actually doesn’t prevent direct access from a remote application. To really force the RMI registry to only listen for connection from the local host we would likely need to set – under Sun JVM without Spring – the system property com.sun.management.jmxremote. Additionally, to force the registry to use the IP 120.0.0.1, we’d need to set java.rmi.server.hostname=localhost (applies to Spring too). See this discussion about forcing local access. I’m not sure how to achieve the same result with Spring while still preserving the ability to specify both the RMI ports. Check also the JavaDoc for Spring’s RmiServiceExporter . Related posts and docs: Tunneling Debug and JMX for Alfresco (A. uses Spring)- see the second section, SSH Tunneling for JMX A custom tunneling RMI agent – uses a configured port instead of a random one Monitoring ActiveMQ Using JMX Over SSH JMX 1.2 specification and JMX 1.0 Remote API specification; from the JMX spec.: “The MBean server relies on protocol adaptors and connectors to make the agent accessible from management applications outside the agent’s JVM.” On the other hand, the Oracle JMX page reads that if you set com.sun.management.jmxremote (as opposed to …jmxremote.port), you make it possible “to monitor a local Java platform, that is, a JVM running on the same machine” – thus not necessarily from the same JVM. Connecting with JConsole Fire up JConsole and type the appropriate remote address, for example service:jmx:rmi:///jndi/rmi://your.server.com:10099/myconnector, if connecting to an application on the remote machine your.server.com accessible via RMI. Regarding the connection URL, if you have a a connector with the serviceUrl of "service:jmx:rmi://myhost:9999/jndi/rmi://localhost:10099/myconnector" then, from a client, you can use either service:jmx:rmi://myhost:9999/jndi/rmi://your.server.com:10099/myconnector or simply service:jmx:rmi:///jndi/rmi://your.server.com:10099/myconnector because, according to the JMX 1.2 Remote API specification (page 90): ... the hostname and port number # (myhost:9999 in the examples) are not used by the client and, if # present, are essentially comments. The connector server address # is actually stored in the serialized stub (/stub/ form) or in the # directory entry (/jndi/ form). IBM JVM, JConsole and JMX configuration The IBM JVM 5 SDK guide indicates that the IBM SDK also contains JConsole and recognizes the same JMX-related system properties, namely com.sun.management.jmxremote.* (though “com.sun.management.jmxremote” itself isn’t mentioned). Notice that the IBM JConsole is a bit different, for instance it’s missing the Local tab, which is replaced by specifying the command-line option connection=localhost (search the SDK guide for “JConsole monitoring tool Local tab”). Further improvements JVM 1.5: Exposing the MemoryMXBean Since Java 5.0 there is a couple of useful platform MBeans that provide information about the JVM, including also the java.lang.management.MemoryMXBean, that let you see the heap usage, invoke GC etc. You can make it available to JConsole and other JMX agents as follows (though there must be an easier way): Update: There indeed seems to be a better way of exposing the platform MBeans directly by replacing the Spring’s MBeanServerFactoryBean with java.lang.management.ManagementFactory using its factory-method getPlatformMBeanServer. Of course this requires JVM 1.5+. Improving security with password authentication Access to your MBeans over RMI may be protected with a password. According to a discussion, authentication is configured on the server connector: The passwd and access files follow the templates that can be found in the JDK/jre/lib/management folder. Summary Exposing a POJO as a MBean with Spring is easy, just don’t forget to start an MBean server and a connector. For JMXMP, include the jmxmp impl. jar on the classpath and for RMI make sure to start a RMI registry before the connector. From http://theholyjava.wordpress.com/2010/09/16/exposing-a-pojo-as-a-jmx-mbean-easily-with-spring/
September 17, 2010
by Jakub Holý
· 37,662 Views
article thumbnail
Throwing Undeclared Checked Exceptions
Sometimes checked exceptions can be a problem. For instance, recently I tried to implement some common logic to retry failing network operations and it resulted in a kind of command pattern on which, as usual, the execute() method throws java.lang.Exception. That complicated the caller code which has to catch and handle java.lang.Exception instead of the more specific exceptions... I knew that checked exceptions are enforced by the compiler, while in the virtual machine there is nothing preventing a checked exception to be thrown by a method not declaring it, so I started to check on internet how to implement this. I found two posts on Anders Noras's blog (#1 #2) on how to perform this magic. Method #1: the sun.misc.Unsafe class import java.lang.reflect.Field; import sun.misc.Unsafe; public class UnsafeSample { public void methodWithNoDeclaredExceptions( ) { Unsafe unsafe = getUnsafe(); unsafe.throwException( new Exception( "this should be checked" ) ); } private Unsafe getUnsafe() { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch(Exception e) { throw new RuntimeException(e); } } public static void main( String[] args ) { new UnsafeSample().methodWithNoDeclaredExceptions(); } } This makes use of internal Sun JRE libraries implementation classes. It could not work if you use a non Sun VM. And in fact it doesn't if you use GCJ (The GNU compiler for Java). The getUnsafe() method exposed above does some tricks to access a private field in the Unsafe class, because Unsafe.getUnsafe() can only be called by classes loaded by the bootstrap ClassLoader. See also the article Avoiding Checked Exceptions by Don Schwarz. Method #2: the Thread.stop(Exception) public class ThreadStopExample { @SuppressWarnings("deprecation") public void methodWithNoDeclaredExceptions( ) { Thread.currentThread().stop(new Exception( "this should be checked" )); } public static void main( String[] args ) { new ThreadStopExample().methodWithNoDeclaredExceptions(); } } This uses a deprecated method, but works. No portability issue, until the Java specification guys decide to remove the method. It could have some side effects on the current thread as we are calling stop(). I'm not sure. Method #3: using Class.newInstance() Look at the signature of java.lang.Class.newInstance() and compare it to Constructor.newInstance() public final class Class ... { public T newInstance() throws InstantiationException, IllegalAccessException } public final class Constructor ... { public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException } You see it? no InvocationTargetException! If you call SomeObject.class.newInstance() and the constructor throws an exception, the exception doesn't get wrapped into the InvocationTargetException (that is a checked exception). So you can write an utility class like this, to throw checked exceptions without needing to declare them on the method signature. public class Exceptions { private static Throwable throwable; private Exceptions() throws Throwable { throw throwable; } public static synchronized void spit(Throwable throwable) { Exceptions.throwable = throwable; try { Exceptions.class.newInstance(); } catch(InstantiationException e) { } catch(IllegalAccessException e) { } finally { Exceptions.throwable = null; } } } public class TestExceptionSpit { public static void main(String[] args) { Exceptions.spit(new Exception( "this should be checked" )); } } Internally the Class.newInstance() uses the sun.misc.Unsafe class, but in this case this technique is fully portable because you are not using any deprecated or internal method. In fact it works also with GCJ JVM. I tried to remove the synchronization stuff and the static field using an inner class, but it seems that the compiler does some strange trick translating the empty constructor in something else preventing Class.newInstace() to be used on that inner class. The behavior of the Class.newInstance() is also documented: "Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler." So your code is fully safe and compliant to the rules :) Method #4: the sun.corba.Bridge import java.rmi.RemoteException; public class Bridge { public void methodWithNoDeclaredExceptions( ) { sun.corba.Bridge.get().throwException(new RemoteException("bang!")); } public static void main( String[] args ) { new Bridge().methodWithNoDeclaredExceptions(); } } This is more or less the same as using the Unsafe.class. The difference is that in this case you don't need to do the reflection stuff to access the private field "theUnsafe", because the Bridge class is doing that for you. Still using an internal JRE class with same portability issues. Method #5: Generics The following example takes advantage of the fact that the compiler does not type check generics... import java.rmi.RemoteException; class Thrower { public static void spit(final Throwable exception) { class EvilThrower { @SuppressWarnings("unchecked") private void sneakyThrow(Throwable exception) throws T { throw (T) exception; } } new EvilThrower().sneakyThrow(exception); } } public class ThrowerSample { public static void main( String[] args ) { Thrower.spit(new RemoteException("go unchecked!")); } } Credits to "Harald" that posted a comment on Johannes Brodwall's blog. I personally think this last one is the best solution: it uses a feature of the compiler against itself. Conclusions I think that having checked exception in Java is better than not having it. I already expressed why I am in favor of checked exceptions here. It's a design decision, you can choose to make your exceptions checked or unchecked, if you want to force your client to handle them or not; you can't do that on .NET, where checked exceptions simply do not exist. Sometimes you have (or you have to write) methods throwing java.lang.Exception, and you get into the trap. So you may like to know that there is a dirty escape, and you can decide to use it or not... we saw that Sun is throwing undeclared checked exceptions in Class.newInstace(), ask yourself: if this is good for the JRE code, could it be good also for yours? Usually you can wrap checked exception into RuntimeExceptions but this doesn't simplify the client code, because the caller in case of needing has to catch the RuntimeException, unwrap the cause and deal with it. Maybe a new Java keyword to throw checked exception without requiring the caller to handle them could help: I recommend reading post on Ricky Clarkson's about checked exceptions. Finally I come to the decision to not use those tricks in my object doing the retry logic, and keep the messy catch logic on the caller code. In case of needing I will evaluate to use a Dynamic Proxy doing the retry logic and keeping its behavior transparent to the client. To those who wants unchecked exceptions in Java... well, there is the way to have it: the example with Generics is a clean way to have it. Use it if you want, at your own risk. Personally I would choose to use libraries with checked exceptions... Other related articles Friday Free Stuff by Chris Nokleberg, uses bytecode manipulation. Don't Try This at Home by Bob Lee, exposes some methods also covered above. From: http://en.newinstance.it/2008/11/17/throwing-undeclared-checked-exceptions/
September 15, 2010
by Luigi Viggiano
· 26,302 Views
article thumbnail
Java Swing Components Accordion Skinning Tutorial
Before we can begin skinning a JSCAccordion, we need to first decide on what look we want to achieve. After much searching I came across an attractive asp.net accordion which I though would make the perfect subject for this skinning tutorial. This tutorial will show you how to take the the default accordion and skin it to look like the asp.net accordion. Comparing the asp.net accordion to the standard JSCAccordion, one would imagine that it would take a lot of code to perform the transformation, however this is really not the case. There are a number of options available to us when going about skinning a JSCAccordion, some include extending the existing JSCAccordion, extending an existing AccordionUI, or lastly simply adjusting an accordion's settings in code. I will follow the last approach as I feel this will lead to a simpler demo, but all options are valid. Step 1: Create an instance of JSCAccordion The first step in our tutorial involves creating a new JSCAccordion and adding the required 'Mail', 'Notes' and 'Contacts' tabs. JSCAccordion accordion = new JSCAccordion(); accordion.addTab("Mail", new JLabel()); accordion.addTab("Notes", new JLabel()); accordion.addTab("Contacts", new JLabel()); Although it is possible to add any component to an accordion's tab, we will add a JLabel as they are naturally transparent (non opaque) and will allow us to easily see the tab's background. Step 2: Adjust basic settings on the JSCAccordion In order for us to achieve the layout of the asp.net accordion, we will need to change a few basic settings on the JSCAccordion. We need to change the orientation of the accordion to render vertically. The tab height must be set to 31 pixels. We need to disable the rendering of the accordion's shadows. The asp.net accordion has a border comprising a black then white rectangle. //lays out the accordion's tabs to move vertically. accordion.setTabOrientation(TabOrientation.VERTICAL); //adjusts the height of the tabs to be 31 pixels accordion.setTabHeight(31); //stops the accordion rendering its shadows accordion.setDrawShadow(false); //the asp.net accordion is framed with a black then white border accordion.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(Color.BLACK), BorderFactory.createLineBorder(Color.WHITE)) ); Step 3: Adjusting settings on the SteelAccordionUI In the previous step, we adjusted settings found on the JSCAccordion, however in order to achieve our final look we will need to adjust some settings on the Accordion's UI. The default UI for the Accordion is the SteelAccordionUI, and it is this UI that we will now manipulate. In order to bring us one step closer to the asp.net accordion we will now set all the paddings on the SteelAccordionUI to zero. //we know the default UI for the accordion is the SteelAccordionUI //so we cast the UI to a SteelAccordionUI. SteelAccordionUI steelAccordionUI = (SteelAccordionUI) accordion.getUI(); //we set all the paddings to zero steelAccordionUI.setHorizontalBackgroundPadding(0); steelAccordionUI.setVerticalBackgroundPadding(0); steelAccordionUI.setHorizontalTabPadding(0); steelAccordionUI.setVerticalTabPadding(0); steelAccordionUI.setTabPadding(0) Setting all the paddings to zero yields us the following result. Step 4: Replace the background painter All components from Java Swing Components make use of painters to achieve their look and feel. A painter is a simple class that contains logic to paint (draw) a component. The advantage of keeping this logic in a painter is two fold, firstly its easy to write new painters and secondly all painters are interchangeable. The net result of this is that it becomes very easy to change how a component looks. The framework upon which all components from Java Swing Components relies includes some simple pre-optimized painters. Instead of creating a new painter from scratch, I will simply make use of existing painters. Having a look at the asp.net accordion, we can see that we need to draw a gradient from white to grey horizontally to form the background. In order to achieve this we will make use of the GradientColorPainter. This painter paints a simple gradient starting with the startColor and ending with the endColor in a specified direction. //we will replace the current background painter with a new //GradientColorPainter. GradientColorPainter backgroundPainter = new GradientColorPainter(); //paint gradient horizontally backgroundPainter.setGradientDirection(GradientDirection.HORIZONTAL); //start with white backgroundPainter.setStartColor(new Color(255,255,255)); //end with grey backgroundPainter.setEndColor(new Color(214,213,228)); //apply the painter to the accordion accordion.setBackgroundPainter(backgroundPainter); The result of applying the new background painter renders the following result. Step 5: Create a new AccordionTabRenderer The last step in our skinning process it to code an entirely new AccordionTabRenderer. An AccordionTabRenderer is an interface used by the accordion to 'rubber stamp' a single component for each of the tabs. It works exactly the same as TableCellRenderers on the standard Jtable. The AccordionTabRenderer interface has a single method getTabComponent. public JComponent getTabComponent(GetTabComponentParameter parameters); The JComponent returned by this method will be used to draw the accordion's tabs. It is the responsibility of the AccordionTabRenderer to read the information from the parameters argument and return an appropriately configured component. The advantage of using a renderer is that it saves memory by only making use of a single component for all the tabs and also allows the developer to return any component they want. The only thing to remember is that the component returned is painted on the screen, and is not added to the accordion as a normal component. For all intensive purposes it is being used as a rubber stamp. The easiest component to return for this tutorial would be a label, as it has text and an image, which is exactly what we need. We will create a class called a DemoAccordionTabRenderer that implements AccordionTabRenderer and extends JLabel. Whenever the getTabComponent method is invoked, it will return itself. In the constructor of our class we will load the three images required by the renderer. These images are retrieved in the constructor and not during the getTabComponent method as this would result in io every time a tab is drawn. Unfortunately I did not have access to the icons used in the asp.net accordion so I will be making use of some great icons from the Tango icon library instead. private ImageIcon mailImage; private ImageIcon notesImage; private ImageIcon contactsImage; public DemoAccordionTabRenderer() { try { //images are loaded in the constructor to improve performance. //loading images in the getTabComponent method will result in the images //being loaded every time a tab is drawn. mailImage = new ImageIcon(ImageIO.read(Thread.currentThread() .getContextClassLoader().getResourceAsStream("mail.png"))); notesImage = new ImageIcon(ImageIO.read(Thread.currentThread(). getContextClassLoader().getResourceAsStream("notes.png"))); contactsImage = new ImageIcon(ImageIO.read(Thread.currentThread(). getContextClassLoader().getResourceAsStream("contacts.png"))); } catch (IOException e) { e.printStackTrace(); } } Now for the most important method, the getTabComponent method. In this method we will read the information from the parameters argument and setup our renderer. @Override public JComponent getTabComponent(GetTabComponentParameter parameters) { //read the tabText from the parameter setText(parameters.tabText); //set the text color to white setForeground(Color.WHITE); //use a slightly smaller bold font setFont(getFont().deriveFont(Font.BOLD, 11f)); //create a border to help align the label setBorder(BorderFactory.createEmptyBorder(0,8,0,0)); //set the gap between the icon and the text to 8 pixels setIconTextGap(8); //set the appropriate image based on the tabText. if ("Mail".equals(parameters.tabText)) { setIcon(mailImage); } if ("Notes".equals(parameters.tabText)) { setIcon(notesImage); } if ("Contacts".equals(parameters.tabText)) { setIcon(contactsImage); } //returns itself, which extends JLabel return this; } The final step required to achieve the look of the asp.net accordion is to draw the appropriate background for the AccordionTabRenderer. There are a number of ways this can be achieved, the easiest being to simply override the paintComponent method of the AccordionTabRenderer. The background of the asp.net accordion's tabs is complex linear gradient comprising of a number of colours. In order to achieve the same look, I will be making use of the LinearGradientColorPainter from the Java Swing Components framework. This painter paints a number of gradients together based on a supplied array of colours and floats. The workings of the painter is beyond the scope of this tutorial, however additional information can be found in the Sun (Oracle) api javadocs of LinearGradientPaint. In the paintComponent method, we will paint the tab's background using our LinearGradientColorPainter and then simply call super.paintComponent() to paint the standard JLabel on top of the background. private LinearGradientColorPainter painter = new LinearGradientColorPainter(); @Override protected void paintComponent(Graphics g) { //setup the painter fractions painter.setColorFractions(new float[]{ 0.0f, 0.49f, 0.5f, 0.51f, 0.8f, 1.0f}); //setup the painter colors painter.setColors(new Color[]{ new Color(167,163,189),new Color(143,138,169), new Color(131,126,160),new Color(116,110,146), new Color(119,113,148), new Color(138,133,164)}); //paint the background painter.paint((Graphics2D) g, new Rectangle(0, 0, getWidth(), getHeight())); //original color on g is stored and then later reset //this is to prevent clobbering of the Graphics object. Color originalColor = g.getColor(); //paints a simple line on the bottom of the tab g.setColor(new Color(87,86,111)); g.drawLine(0, getHeight()-1, getWidth(), getHeight()-1); g.setColor(originalColor); //draws the label on top of the background we just painted. super.paintComponent(g); } The last step is to assign our custom AccordionTabRenderer to the accordion. //apply the new TabRenderer to the accordion. accordion.setVerticalAccordionTabRenderer(new DemoAccordionTabRenderer()); The final result of all our hard work can be seen in the image below. Although it may have felt like a lot of code, seeing all the code together really shows how easy the skinning process is. JSCAccordion accordion = new JSCAccordion(); accordion.addTab("Mail", new JLabel()); accordion.addTab("Notes", new JLabel()); accordion.addTab("Contacts", new JLabel()); //lays out the accordion's tabs to move vertically. accordion.setTabOrientation(TabOrientation.VERTICAL); //adjusts the height of the tabs to be 31 pixels accordion.setTabHeight(31); //stops the accordion rendering its shadows accordion.setDrawShadow(false); //the asp.net accordion has a border comprising a black then white border accordion.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.BLACK),BorderFactory.createLineBorder(Color.WHITE))); //we know the default UI for the accordion is the SteelAccordionUI SteelAccordionUI steelAccordionUI = (SteelAccordionUI) accordion.getUI(); //we set all the paddings to zero steelAccordionUI.setHorizontalBackgroundPadding(0); steelAccordionUI.setVerticalBackgroundPadding(0); steelAccordionUI.setHorizontalTabPadding(0); steelAccordionUI.setVerticalTabPadding(0); steelAccordionUI.setTabPadding(0); //we will replace the current background painter with a new //GradientColorPainter. GradientColorPainter backgroundPainter = new GradientColorPainter(); //paint gradient horizontally backgroundPainter.setGradientDirection(GradientDirection.HORIZONTAL); //start with white backgroundPainter.setStartColor(new Color(255,255,255)); //end with grey backgroundPainter.setEndColor(new Color(214,213,228)); //apply the painter to the accordion accordion.setBackgroundPainter(backgroundPainter); //apply the new TabRenderer to the accordion. accordion.setVerticalAccordionTabRenderer(new DemoAccordionTabRenderer()); This brings us to the end of the tutorial, for those of you who are made it this far, the final demo jar and source code have been attached to this article. Enjoy
September 13, 2010
by Rhiannon Liebowitz
· 34,140 Views · 2 Likes
article thumbnail
Java: Overriding Getters and Setters Design
Why do we keep instance variables private? We don’t want other classes to depend on them. Moreover it gives the flexibility to change a variable’s type or implementation on a whim or an impulse. Why, then programmers automatically add or override getters and setters to their objects, exposing their private variables as if they were public? Accessor methods Accessors (also known as getters and setters) are methods that let you read and write the value of an instance variable of an object. public class AccessorExample { private String attribute; public String getAttribute() { return attribute; } public void setAttribute(String attribute) { this.attribute = attribute; } } Why Accessors? There are actually many good reasons to consider using accessors rather than directly exposing fields of a class Getter and Setter make API more stable. For instance, consider a field public in a class which is accessed by other classes. Now, later on, you want to add any extra logic while getting and setting the variable. This will impact the existing client that uses the API. So any changes to this public field will require a change to each class that refers it. On the contrary, with accessor methods, one can easily add some logic like cache some data, lazily initialize it later. Moreover, one can fire a property changed event if the new value is different from the previous value. All this will be seamless to the class that gets the value using accessor method. Should I have Accessor Methods for all my fields? Fields can be declared public for package-private or private nested class. Exposing fields in these classes produces less visual clutter compare to accessor-method approach, both in the class definition and in the client code that uses it. If a class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields—assuming they do an adequate job of describing the abstraction provided by the class. Such code is restricted to the package where the class is declared, while the client code is tied to class internal representation. We can change it without modifying any code outside that package. Moreover, in the case of a private nested class, the scope of the change is further restricted to the enclosing class. Another example of a design that uses public fields is JavaSpace entry objects. Ken Arnold described the process they went through to decide to make those fields public instead of private with get and set methods here Now this sometimes makes people uncomfortable because they've been told not to have public fields; that public fields are bad. And often, people interpret those things religiously. But we're not a very religious bunch. Rules have reasons. And the reason for the private data rule doesn't apply in this particular case. It is a rare exception to the rule. I also tell people not to put public fields in their objects, but exceptions exist. This is an exception to the rule, because it is simpler and safer to just say it is a field. We sat back and asked: Why is the rule thus? Does it apply? In this case it doesn't. Private fields + Public accessors == encapsulation Consider the example below public class A { public int a; } Usually, this is considered bad coding practice as it violates encapsulation. The alternate approach is public class A { private int a; public void setA(int a) { this.a =a; } public int getA() { return this.a; } } It is argued that this encapsulates the attribute. Now is this really encapsulation? The fact is, Getters/setters have nothing to do with encapsulation. Here the data isn't more hidden or encapsulated than it was in a public field. Other objects still have intimate knowledge of the internals of the class. Changes made to the class might ripple out and enforce changes in dependent classes. Getter and setter in this way are generally breaking encapsulation. A truly well-encapsulated class has no setters and preferably no getters either. Rather than asking a class for some data and then compute something with it, the class should be responsible for computing something with its data and then return the result. Consider an example below, public class Screens { private Map screens = new HashMap(); public Map getScreens() { return screens; } public void setScreens(Map screens) { this.screens = screens; } // remaining code here } If we need to get a particular screen, we do code like below, Screen s = (Screen)screens.get(screenId); There are things worth noticing here.... The client needs to get an Object from the Map and casting it to the right type. Moreover, the worst is that any client of the Map has the power to clear it which may not be the case we usually want. An alternative implementation of the same logic is: public class Screens { private Map screens = new HashMap(); public Screen getById(String id) { return (Screen) screens.get(id); } // remaining code here } Here the Map instance and the interface at the boundary (Map) are hidden. Getters and Setters are highly Overused Creating private fields and then using the IDE to automatically generate getters and setters for all these fields is almost as bad as using public fields. One reason for the overuse is that in an IDE it’s just now a matter of few clicks to create these accessors. The completely meaningless getter/setter code is at times longer than the real logic in a class and you will read these functions many times even if you don't want to. All fields should be kept private, but with setters only when they make sense which makes object Immutable. Adding an unnecessary getter reveals internal structure, which is an opportunity for increased coupling. To avoid this, every time before adding the accessor, we should analyse if we can encapsulate the behaviour instead. Let’s take another example, public class Money { private double amount; public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; } //client Money pocketMoney = new Money(); pocketMoney.setAmount(15d); double amount = pocketMoney.getAmount(); // we know its double pocketMoney.setAmount(amount + 10d); } With the above logic, later on, if we assume that double is not a right type to use and should use BigDecimal instead, then the existing client that uses this class also breaks. Let’s restructure the above example, public class Money { private BigDecimal amount; public Money(String amount) { this.amount = new BigDecimal(amount); } public void add(Money toAdd) { amount = amount.add(toAdd.amount); } // client Money balance1 = new Money("10.0"); Money balance2 = new Money("6.0"); balance1.add(balance2); } Now instead of asking for a value, the class has a responsibility to increase its own value. With this approach, the change request for any other datatype in future requires no change in the client code. Here not only the data is encapsulated but also the data which is stored, or even the fact that it exists at all. Conclusions Use of accessors to restrict direct access to field variable is preferred over the use of public fields, however, making getters and setter for each and every field is overkill. It also depends on the situation though, sometimes you just want a dumb data object. Accessors should be added to a field where they're really required. A class should expose larger behaviour which happens to use its state, rather than a repository of state to be manipulated by other classes. More Reading http://c2.com/cgi/wiki?TellDontAsk http://c2.com/cgi/wiki?AccessorsAreEvil Effective Java - See more at http://muhammadkhojaye.blogspot.co.uk/2010/10/getter-setter-to-use-or-not-to-use.html
September 10, 2010
by Muhammad Ali Khojaye
· 98,296 Views · 1 Like
article thumbnail
Server Centric Java Frameworks: Performance Comparison
These days we are used to AJAX-intensive, sophisticated web frameworks. These frameworks provide us desktop style development into the Single Page Interface (SPI) paradigm. As you know there are two main types of frameworks, client-centric and server-centric. Each approach has pros and cons. Testing the performance of Java server-centric frameworks In the server-centric view, state is managed in server. In some way the client is a sophisticated terminal of the server because most of visual decisions are taken on the server and some kind of visual rendering is done on the server (HTML generation as markup or embedded in JavaScript or more higher level code sent to the client). The main advantage is that data and visual rendering are together in the same memory space, avoiding custom client-server bridges for data communication and synchronization, typical of the client-centric approach. This article only reviews Java server-centric frameworks. In SPI, the web page is partially changed; that is, some HTML parts can be removed and some new HTML markup can be inserted. This approach obviously saves tons of bandwidth and computer power because the complete page is not rebuilt and not fully sent to the client when some page change happens. A server-centric framework to be effective must send to the client ONLY the markup going to be changed or equivalent instructions in some form, when some AJAX event hits the server. This article reviews how much effective most of the SPI Java web frameworks are on partial changes provided by the server. We are not interested in events with no server communication, that is, events with no (possible) server control. How they are going to be measured We are going to measure the amount of code that is sent to client regarding to the visual change performed in client. For instance for a minor visual change (some new data) in a component we expect not much code from server, that is, the new markup needed as plain HTML, or embedded in JavaScript, or some high level instructions containing the new data to be visualized. Otherwise something seems wrong for instance the complete component or page zone is rebuilt, wasting bandwidth and client power (and maybe server power). Because we will use public demos, we are not going to get a definitive and fine grain benchmark. But you will see very strong differences between frameworks. The testing technique is very easy and everybody can do it with no special infrastructure, we just need FireFox and FireBug. In this test FireFox 3.6.8 and FireBug 1.5.4 are used. The FireBug Console when "Show XMLHttpRequests" is enabled logs any AJAX request showing the server response. The process is simple: The Console will be enabled before loading the page with the demo. Some clicks will drive some concrete component to the desired state. A final click will perform a small change in the component being analyzed. Then we will copy the output code of the AJAX request (HTML, XML, JavaScript ...) sent from server. The more code the less effective, more bandwidth waste and client processing is needed. We cannot measure the server power used because we need a deep knowledge of how the framework works in server, said this we can easily "suspect" the more code generated in server the more server power is wasted. Frameworks tested RichFaces, IceFaces, MyFaces/Trinidad, OpenFaces, PrimeFaces, Vaadin, ZK, ItsNat ADF Faces is not tested because there is no longer a public live demo. Because ADF Faces is based on Trinidad, Trinidad analysis could be extrapolated to ADF Faces (?). Update: NO, ADF Faces are very different to Trinidad. Note before starting Some frameworks seem to perform very well (regarding to this kind of test), that is, the ratio between visual change and amount of code is acceptable, but in some concrete cases (components) they "miserably" fail. This article tries to measure bad performant components. RichFaces Console must be enabled, configured and open as seen before. Open this tree demo (Ajax switch type) Expand "Baccara" node Expand "Grand Collection" Collapse "Grand Collection" As you can see the child nodes below "Grand Collection" has been removed or hidden (FireBug's DOM inspector says they were removed). Grand Collection As you can see too much HTML code has been sent for not much of a visual change. A more severe performance penalty: Open the Extended Data Table Demo On "State Name" paste "Alaska" (paste the name from clipboard), one row is shown Paste "Alabama" replacing "Alaska" (again paste from clipboard selecting Alaska first), again one different row is shown. The answer (HTML code) is too big to put here, 3.474 bytes, if you inspect the result you will see a complete rewrite of the table including header. IceFaces Open the Calendar demo Click on any different day Something like this is the last AJAX response: The answer (XML with metadata) is really big, 6.452 bytes, for a simple day change according to visual changes. MyFaces/Trinidad Open this Tree Table Demo Expand node_0_0 Expand node_0_0_0 (node node_0_0_0_ is shown) Collapse node_0_0_0 (hides/removes node_0_0_0_0) The last AJAX response is too big to put here, 18.765 bytes, because is a complete rewrite of the tree component. Update: a live demo of ADF Faces components is here and they seem to work fine as expected, that is, the ratio between code sent to the client and visual change is "correct" (in spite of HTML layout is very verbose the code sent to the client is almost the same to be displayed). OpenFaces Open the Tree Table demo Expand "Re: Scalling an image" Expand the new child "Re: Scalling an image" The last AJAX response is Re: Scaling an imageChristian SmileAug 3, 2007" data="{"structureMap":{"0":"1"}" scripts="" /> This code is very reasonable according to the change (a new child node/table row). Nevertheless some component miserably fails: Open the Data Table demo Select "AK" as "State", resulting one row. Replace with "AR", resulting again a new row The last AJAX result is too big, 38.209 bytes, because is a complete rewrite of the table including headers. PrimeFaces The AJAX answers of all tested examples were very reasonable. Said this, PrimeFaces lacks of a "filtered table component" or similar, the Achilles's heel of other JSF implementations. Update: As Cagatay Civici (one of the fathers of PrimeFaces) points out, PrimeFaces has a filltered table, this component works fine regarding to the ratio of visual change/code sent to client (try to do the same tests as prvious frameworks). Vaadin This is the first non-JSF framework. Open the Tree single selection demo Select "Dell OptiPlex GX240" Click "Apply" button (no change is needed) This is the last AJAX answer: for(;;);[{"changes":[["change",{"format": "uidl","pid": "PID190"},["12",{"id": "PID190","immediate":true,"caption": "Hardware Inventory","selectmode": "single","nullselect":true,"v":{"action":"","selected":["2"],"expand":[],"collapse":[],"newitem":[]},["node",{"caption": "Desktops","key": "1","expanded":true,"al":["1","2"]},["leaf",{"caption": "Dell OptiPlex GX240","key": "2","selected":true,"al":["1","2"]}],["leaf",{"caption": "Dell OptiPlex GX260","key": "3","al":["1","2"]}],["leaf",{"caption": "Dell OptiPlex GX280","key": "4","al":["1","2"]}]],["node",{"caption": "Monitors","key": "5","expanded":true,"al":["1","2"]},["leaf",{"caption": "Benq T190HD","key": "6","al":["1","2"]}],["leaf",{"caption": "Benq T220HD","key": "7","al":["1","2"]}],["leaf",{"caption": "Benq T240HD","key": "8","al":["1","2"]}]],["node",{"caption": "Laptops","key": "9","expanded":true,"al":["1","2"]},["leaf",{"caption": "IBM ThinkPad T40","key": "10","al":["1","2"]}],["leaf",{"caption": "IBM ThinkPad T43","key": "11","al":["1","2"]}],["leaf",{"caption": "IBM ThinkPad T60","key": "12","al":["1","2"]}]],["actions",{},["action",{"caption": "Add child item","key": "1"}],["action",{"caption": "Delete","key": "2"}]]]]], "meta" : {}, "resources" : {}, "locales":[]}] It seems not very much, but if you review the code the entire tree is being rebuilt again. ZK Another non-JSF framework. In the last versions ZK embrace an hybrid approach, most of the visual logic is in client as JavaScript components, the server sends to the client high level commands to the high level client library (Vaadin is not different). I have not found a component sending too much code from client (according to the visual change) in ZK's demo. ItsNat The last framework studied, again a non-JSF framework. In ItsNat the server keeps the same DOM state as in client and through DOM mutation events any change to the DOM in server automatically generates the JavaScript necessary to update the client accordingly. Open the demo Click on the handler of "Core" folder, the child nodes (11) are hidden. Result code of the AJAX event: itsNatDoc.addNodeCache(["cn_10","cn_14","0,1,1,0,0",["cn_15","cn_16"]]); itsNatDoc.setAttribute2("cn_14","src","img/tree/tree_node_collapse.gif"); itsNatDoc.setAttribute2(["cn_15","cn_17","1"],"src","img/tree/tree_folder_close.gif"); itsNatDoc.setAttribute2(["cn_16","cn_18","1,0",["cn_19"]],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_20","1"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_21","2"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_22","3"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_23","4"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_24","5"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_25","6"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_26","7"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_27","8"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_28","9"],"style","display:none"); itsNatDoc.setAttribute2(["cn_19","cn_29","10"],"style","display:none"); No surprises. Another test Open this Tree demo Click on "Insert Child". A new child node ("Actors") is inserted and a new log message is added. AJAX result code: itsNatDoc.removeAttribute2(["cn_15","cn_39","13"],"style"); itsNatDoc.setInnerHTML2("cn_39"," clickjavax.swing.event.TreeModelEvent 13802934 path [Grey's Anatomy, Actors] indices [ 4 ] children [ Actors ]"); var child = itsNatDoc.doc.createElement("li"); itsNatDoc.setAttribute(child,"style","padding:1px;"); itsNatDoc.appendChild2(["cn_17","cn_40","0,1,1,1",["cn_41","cn_42"]],child); itsNatDoc.setInnerHTML(child,"Label\n \n "); itsNatDoc.setTextData2(["cn_40","cn_43","4,0,2,0",["cn_44","cn_45"]],null,"Actors"); itsNatDoc.setAttribute2(["cn_45","cn_46","0"],"style","display:none"); itsNatDoc.setAttribute2(["cn_45","cn_47","1"],"src","img/tree/gear.gif"); Again no surprises. And the Winner is... There is no winner because only some components have been tested. Having said this, apparently the only JSF implementation free of serious performance penalties is PrimeFaces. In non-JSF frameworks using a very high level JS library like in Vaadin or ZK (PrimeFaces?) helps very much to reduce the network bandwidth (in spite of the fact that some components in Vaadin have serious performance problems), this cannot be said for client performance because in ItsNat the exact JS DOM code is sent to the client. On the other side a high level JS library complicates custom component development (beyond composition) because the server does not help very much but this is another story, and another article.
September 7, 2010
by Jose Maria Arranz
· 23,106 Views
article thumbnail
Storing passwords in Java web application
First of all, you should never store passwords. Then why the heck am I writing this post? Okay, Let me rephrase the first sentence – You should never store passwords as plain text anywhere in your application. of course, for the obvious reasons. If you store passwords as plain text, in a database or in a log file, then even Rajinikanth couldn’t save your application getting **cked.. I mean hacked. (Btw, Rajinikanth is the Chuck Norris of India, if you are not aware of him) Then what’s the right way to deal with the asterisks? You could use encryption. But if there’s a way to encrypt it, then there should be a way to decrypt it. So, encryption is also vulnerable to hacker’s attack. Isn’t there a better solution to this? It’s there and it's known as Password Hashing. How password hashing works? In hashing, you take a input string (in our case, a password), add a salt to the string, generate the hash value (using SHA-1 algorithm for example), and store the hash value in DB. For matching passwords while login, you do the same hashing process again and match the hash value instead of matching plain passwords and authenticate users. Hashing is different from encryption. Because, encryption is two way, means that you can always decrypt the encrypted text to get the original text. But Hashing is one way, you can never get the original text from the hash value. Thus it gives more security than encryption. To generate hash, you can make use of any hashing algorithms out there – MD5, SHA-1, etc. Before generating a hash, adding a salt to the password will give added security. Salt is nothing but a simple text that is known only to you/your application. It can be “zebra” or “I’mGod” or anything you wish. Below, I’m giving a Java example of how to do password hashing in an login module. Password hashing example in Java This is simple example containing two methods – signup() and login(). As their names suggest, signup would store username and password in DB and login would check the credentials entered by user against the DB. Let’s dive into the code. package com.sandbox; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; import java.util.Map; public class PasswordHashingDemo { Map DB = new HashMap(); public static final String SALT = "my-salt-text"; public static void main(String args[]) { PasswordHashingDemo demo = new PasswordHashingDemo(); demo.signup("john", "dummy123"); // login should succeed. if (demo.login("john", "dummy123")) System.out.println("user login successfull."); // login should fail because of wrong password. if (demo.login("john", "blahblah")) System.out.println("User login successfull."); else System.out.println("user login failed."); } public void signup(String username, String password) { String saltedPassword = SALT + password; String hashedPassword = generateHash(saltedPassword); DB.put(username, hashedPassword); } public Boolean login(String username, String password) { Boolean isAuthenticated = false; // remember to use the same SALT value use used while storing password // for the first time. String saltedPassword = SALT + password; String hashedPassword = generateHash(saltedPassword); String storedPasswordHash = DB.get(username); if(hashedPassword.equals(storedPasswordHash)){ isAuthenticated = true; }else{ isAuthenticated = false; } return isAuthenticated; } public static String generateHash(String input) { StringBuilder hash = new StringBuilder(); try { MessageDigest sha = MessageDigest.getInstance("SHA-1"); byte[] hashedBytes = sha.digest(input.getBytes()); char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; for (int idx = 0; idx < hashedBytes.length; ++idx) { byte b = hashedBytes[idx]; hash.append(digits[(b & 0xf0) >> 4]); hash.append(digits[b & 0x0f]); } } catch (NoSuchAlgorithmException e) { // handle error here. } return hash.toString(); } } So, that’s it. I guess the above code is self explanatory. Do let me know in case you have any doubts. From http://veerasundar.com/blog/2010/09/storing-passwords-in-java-web-application/
September 7, 2010
by Veera Sundar
· 81,780 Views · 3 Likes
article thumbnail
ExtJS, Spring MVC 3 and Hibernate 3.5: CRUD DataGrid Example
this tutorial will walk through how to implement a crud (create, read, update, delete) datagrid using extjs, spring mvc 3 and hibernate 3.5. what do we usually want to do with data? create (insert) read / retrieve (select) update (update) delete / destroy (delete) until extjs 3.0 we only could read data using a datagrid. if you wanted to update, insert or delete, you had to do some code to make these actions work. now extjs 3.0 (and newest versions) introduces the ext.data.writer, and you do not need all that work to have a crud grid. so… what do i need to add in my code to make all these things working together? in this example, i’m going to use json as data format exchange between the browser and the server. extjs code first, you need an ext.data.jsonwriter: // the new datawriter component. var writer = new ext.data.jsonwriter({ encode: true, writeallfields: true }); where writeallfields identifies that we want to write all the fields from the record to the database. if you have a fancy orm then maybe you can set this to false. in this example, i’m using hibernate, and we have saveorupate method – in this case, we need all fields to updated the object in database, so we have to ser writeallfields to true. this is my record type declaration: var contact = ext.data.record.create([ {name: 'id'}, { name: 'name', type: 'string' }, { name: 'phone', type: 'string' }, { name: 'email', type: 'string' }]); now you need to setup a proxy like this one: var proxy = new ext.data.httpproxy({ api: { read : 'contact/view.action', create : 'contact/create.action', update: 'contact/update.action', destroy: 'contact/delete.action' } }); fyi, this is how my reader looks like: var reader = new ext.data.jsonreader({ totalproperty: 'total', successproperty: 'success', idproperty: 'id', root: 'data', messageproperty: 'message' // <-- new "messageproperty" meta-data }, contact); the writer and the proxy (and the reader) can be hooked to the store like this: // typical store collecting the proxy, reader and writer together. var store = new ext.data.store({ id: 'user', proxy: proxy, reader: reader, writer: writer, // <-- plug a datawriter into the store just as you would a reader autosave: false // <-- false would delay executing create, update, //destroy requests until specifically told to do so with some [save] buton. }); where autosave identifies if you want the data in automatically saving mode (you do not need a save button, the app will send the actions automatically to the server). in this case, i implemented a save button, so every record with new or updated value will have a red mark on the cell left up corner). when the user alters a value in the grid, then a “save” event occurs (if autosave is true). upon the “save” event the grid determines which cells has been altered. when we have an altered cell, then the corresponding record is sent to the server with the ‘root’ from the reader around it. e.g if we read with root “data”, then we send back with root “data”. we can have several records being sent at once. when updating to the server (e.g multiple edits). and to make you life even easier, let’s use the roweditor plugin, so you can easily edit or add new records. all you have to do is to add the css and js files in your page: add the plugin on you grid declaration: var editor = new ext.ux.grid.roweditor({ savetext: 'update' }); // create grid var grid = new ext.grid.gridpanel({ store: store, columns: [ {header: "name", width: 170, sortable: true, dataindex: 'name', editor: { xtype: 'textfield', allowblank: false }, {header: "phone #", width: 150, sortable: true, dataindex: 'phone', editor: { xtype: 'textfield', allowblank: false }, {header: "email", width: 150, sortable: true, dataindex: 'email', editor: { xtype: 'textfield', allowblank: false })} ], plugins: [editor], title: 'my contacts', height: 300, width:610, frame:true, tbar: [{ iconcls: 'icon-user-add', text: 'add contact', handler: function(){ var e = new contact({ name: 'new guy', phone: '(000) 000-0000', email: '[email protected]' }); editor.stopediting(); store.insert(0, e); grid.getview().refresh(); grid.getselectionmodel().selectrow(0); editor.startediting(0); } },{ iconcls: 'icon-user-delete', text: 'remove contact', handler: function(){ editor.stopediting(); var s = grid.getselectionmodel().getselections(); for(var i = 0, r; r = s[i]; i++){ store.remove(r); } } },{ iconcls: 'icon-user-save', text: 'save all modifications', handler: function(){ store.save(); } }] }); java code finally, you need some server side code. controller: package com.loiane.web; @controller public class contactcontroller { private contactservice contactservice; @requestmapping(value="/contact/view.action") public @responsebody map view() throws exception { try{ list contacts = contactservice.getcontactlist(); return getmap(contacts); } catch (exception e) { return getmodelmaperror("error retrieving contacts from database."); } } @requestmapping(value="/contact/create.action") public @responsebody map create(@requestparam object data) throws exception { try{ list contacts = contactservice.create(data); return getmap(contacts); } catch (exception e) { return getmodelmaperror("error trying to create contact."); } } @requestmapping(value="/contact/update.action") public @responsebody map update(@requestparam object data) throws exception { try{ list contacts = contactservice.update(data); return getmap(contacts); } catch (exception e) { return getmodelmaperror("error trying to update contact."); } } @requestmapping(value="/contact/delete.action") public @responsebody map delete(@requestparam object data) throws exception { try{ contactservice.delete(data); map modelmap = new hashmap(3); modelmap.put("success", true); return modelmap; } catch (exception e) { return getmodelmaperror("error trying to delete contact."); } } private map getmap(list contacts){ map modelmap = new hashmap(3); modelmap.put("total", contacts.size()); modelmap.put("data", contacts); modelmap.put("success", true); return modelmap; } private map getmodelmaperror(string msg){ map modelmap = new hashmap(2); modelmap.put("message", msg); modelmap.put("success", false); return modelmap; } @autowired public void setcontactservice(contactservice contactservice) { this.contactservice = contactservice; } } some observations: in spring 3, we can get the objects from requests directly in the method parameters using @requestparam. i don’t know why, but it did not work with extjs. i had to leave as an object and to the json-object parser myself. that is why i’m using a util class – to parser the object from request into my pojo class. if you know how i can replace object parameter from controller methods, please, leave a comment, because i’d really like to know that! service class: package com.loiane.service; @service public class contactservice { private contactdao contactdao; private util util; @transactional(readonly=true) public list getcontactlist(){ return contactdao.getcontacts(); } @transactional public list create(object data){ list newcontacts = new arraylist(); list list = util.getcontactsfromrequest(data); for (contact contact : list){ newcontacts.add(contactdao.savecontact(contact)); } return newcontacts; } @transactional public list update(object data){ list returncontacts = new arraylist(); list updatedcontacts = util.getcontactsfromrequest(data); for (contact contact : updatedcontacts){ returncontacts.add(contactdao.savecontact(contact)); } return returncontacts; } @transactional public void delete(object data){ //it is an array - have to cast to array object if (data.tostring().indexof('[') > -1){ list deletecontacts = util.getlistidfromjson(data); for (integer id : deletecontacts){ contactdao.deletecontact(id); } } else { //it is only one object - cast to object/bean integer id = integer.parseint(data.tostring()); contactdao.deletecontact(id); } } @autowired public void setcontactdao(contactdao contactdao) { this.contactdao = contactdao; } @autowired public void setutil(util util) { this.util = util; } } contact class – pojo: package com.loiane.model; @jsonautodetect @entity @table(name="contact") public class contact { private int id; private string name; private string phone; private string email; @id @generatedvalue @column(name="contact_id") public int getid() { return id; } public void setid(int id) { this.id = id; } @column(name="contact_name", nullable=false) public string getname() { return name; } public void setname(string name) { this.name = name; } @column(name="contact_phone", nullable=false) public string getphone() { return phone; } public void setphone(string phone) { this.phone = phone; } @column(name="contact_email", nullable=false) public string getemail() { return email; } public void setemail(string email) { this.email = email; } } dao class: package com.loiane.dao; @repository public class contactdao implements icontactdao{ private hibernatetemplate hibernatetemplate; @autowired public void setsessionfactory(sessionfactory sessionfactory) { hibernatetemplate = new hibernatetemplate(sessionfactory); } @suppresswarnings("unchecked") @override public list getcontacts() { return hibernatetemplate.find("from contact"); } @override public void deletecontact(int id){ object record = hibernatetemplate.load(contact.class, id); hibernatetemplate.delete(record); } @override public contact savecontact(contact contact){ hibernatetemplate.saveorupdate(contact); return contact; } } util class: package com.loiane.util; @component public class util { public list getcontactsfromrequest(object data){ list list; //it is an array - have to cast to array object if (data.tostring().indexof('[') > -1){ list = getlistcontactsfromjson(data); } else { //it is only one object - cast to object/bean contact contact = getcontactfromjson(data); list = new arraylist(); list.add(contact); } return list; } private contact getcontactfromjson(object data){ jsonobject jsonobject = jsonobject.fromobject(data); contact newcontact = (contact) jsonobject.tobean(jsonobject, contact.class); return newcontact; } ) private list getlistcontactsfromjson(object data){ jsonarray jsonarray = jsonarray.fromobject(data); list newcontacts = (list) jsonarray.tocollection(jsonarray,contact.class); return newcontacts; } public list getlistidfromjson(object data){ jsonarray jsonarray = jsonarray.fromobject(data); list idcontacts = (list) jsonarray.tocollection(jsonarray,integer.class); return idcontacts; } } if you want to see all the code (complete project will all the necessary files to run this app), download it from my github repository: http://github.com/loiane/extjs-crud-grid-spring-hibernate this was a requested post. i’ve got a lot of comments from my previous crud grid example and some emails. i made some adjustments to current code, but the idea is still the same. i hope i was able answer all the questions. happy coding! from http://loianegroner.com/2010/09/extjs-spring-mvc-3-and-hibernate-3-5-crud-datagrid-example/
September 3, 2010
by Loiane Groner
· 101,033 Views · 1 Like
article thumbnail
Clojure: Mocking
An introduction to clojure.test is easy, but it doesn't take long before you feel like you need a mocking framework. As far as I know, you have 3 options. Take a look at Midje. I haven't gone down this path, but it looks like the most mature option if you're looking for a sophisticated solution. Go simple. Let's take an example where you want to call a function that computes a value and sends a response to a gateway. Your first implementation looks like the code below. (destructuring explained) (defn withdraw [& {:keys [balance withdrawal account-number]}] (gateway/process {:balance (- balance withdrawal) :withdrawal withdrawal :account-number account-number})) No, it's not pure. That's not the point. Let's pretend that this impure function is the right design and focus on how we would test it. You can change the code a bit and pass in the gateway/process function as an argument. Once you've changed how the code works you can test it by passing identity as the function argument in your tests. The full example is below. (ns gateway) (defn process [m] (println m)) (ns controller (:use clojure.test)) (defn withdraw [f & {:keys [balance withdrawal account-number]}] (f {:balance (- balance withdrawal) :withdrawal withdrawal :account-number account-number})) (withdraw gateway/process :balance 100 :withdrawal 22 :account-number 4) ;; => {:balance 78, :withdrawal 22, :account-number 4} (deftest withdraw-test (is (= {:balance 78, :withdrawal 22, :account-number 4} (withdraw identity :balance 100 :withdrawal 22 :account-number 4)))) (run-all-tests #"controller") If you run the previous example you will see the println output and the clojure.test output, verifying that our code is working as we expected. This simple solution of passing in your side effect function and using identity in your tests can often obviate any need for a mock. Solution 2 works well, but has the limitations that only one side-effecty function can be passed in and it's result must be used as the return value. Let's extend our example and say that we want to log a message if the withdrawal would cause insufficient funds. (Our gateway/process and log/write functions will simply println since this is only an example, but in production code their behavior would differ and both would be required) (ns gateway) (defn process [m] (println "gateway: " m)) (ns log) (defn write [m] (println "log: " m)) (ns controller (:use clojure.test)) (defn withdraw [& {:keys [balance withdrawal account-number]}] (let [new-balance (- balance withdrawal)] (if (> 0 new-balance) (log/write "insufficient funds") (gateway/process {:balance new-balance :withdrawal withdrawal :account-number account-number})))) (withdraw :balance 100 :withdrawal 22 :account-number 4) ;; => gateway: {:balance 78, :withdrawal 22, :account-number 4} (withdraw :balance 100 :withdrawal 220 :account-number 4) ;; => log: insufficient funds Our new withdraw implementation calls two functions that have side effects. We could pass in both functions, but that solution doesn't seem to scale very well as the number of passed functions grows. Also, passing in multiple functions tends to clutter the signature and make it hard to remember what is the valid order for the arguments. Finally, if we need withdraw to always return a map showing the balance and withdrawal amount, there would be no easy solution for verifying the string sent to log/write. Given our implementation of withdraw, writing a test that verifies that gateway/process and log/write are called correctly looks like a job for a mock. However, thanks to Clojure's binding function, it's very easy to redefine both of those functions to capture values that can later be tested. The following code rebinds both gateway/process and log/write to partial functions that capture whatever is passed to them in an atom that can easily be verified directly in the test. (ns gateway) (defn process [m] (println "gateway: " m)) (ns log) (defn write [m] (println "log: " m)) (ns controller (:use clojure.test)) (defn withdraw [& {:keys [balance withdrawal account-number]}] (let [new-balance (- balance withdrawal)] (if (> 0 new-balance) (log/write "insufficient funds") (gateway/process {:balance new-balance :withdrawal withdrawal :account-number account-number})))) (deftest withdraw-test (let [result (atom nil)] (binding [gateway/process (partial reset! result)] (withdraw :balance 100 :withdrawal 22 :account-number 4) (is (= {:balance 78, :withdrawal 22, :account-number 4} @result))))) (deftest withdraw-test (let [result (atom nil)] (binding [log/write (partial reset! result)] (withdraw :balance 100 :withdrawal 220 :account-number 4) (is (= "insufficient funds" @result))))) (run-all-tests #"controller") In general I use option 2 when I can get away with it, and option 3 where necessary. Option 3 adds enough additional code that I'd probably look into Midje quickly if I found myself writing a more than a few tests that way. However, I generally go out of my way to design pure functions, and I don't find myself needing either of these techniques very often. From http://blog.jayfields.com/2010/09/clojure-mocking.html
September 2, 2010
by Jay Fields
· 6,908 Views
article thumbnail
5 Important Points about Java Generics
Generics allows a type or method to operate on objects of various types while providing compile-time type safety, making Java a fully statically typed language.
August 31, 2010
by Shekhar Gulati
· 159,510 Views · 11 Likes
article thumbnail
How to Migrate from Ant to Maven: Project Structure
I’ve seen my fair share of projects migrating from Ant to Maven, and, for a complex project, this migration path can take some time. You have to worry about dependency management, project structure, and retraining an existing team to use Maven and understand the core concepts behind the tool. When you make the shift, you are often affecting development infrastructure for an existing project, and you need to take into account development environments as well as developer’s ideas about how code should be organized and stored in source control. In this post, I’m going to discuss a common pattern I’ve seen in Ant to Maven migrations: how to migrate the monolithic project. A Common Pattern: The Monolithic Project Ant projects which have evolved over many years often lack modular structure. While it is certainly possible to create the equivalent of a multi-module Maven project in Ant, the usual progression in an Ant project is to store all of your source in a single tree and use extra targets to selectively compile different packages. This approach is shown in the following figure. In the most extreme cases, there is a single project which contains an array of modules. Maybe you have an entire enterprise system all stored in a single project alongside a complex Ant build.xml file which contains a collection of tasks for each component. A monolithic Ant project usually produces a series of artifacts: a JAR containing some API for clients, a server-side web application, a utility library, etc. Developers have usually grown so accustomed to this approach that the idea of splitting up a complex system into a series of related submodules can see daunting. Moving to Maven: Do we need all these projects? One of the first questions I get in a Maven migration from Ant is whether it is really necessary to modularize a project. “Do we really need to create all these projects for Maven?” (Short answer: Yes, there is no avoiding this.) This is usually accompanied by a concern that Maven limits each project to producing a single artifact. These are two core assumptions of Maven: your projects will be modularized and each project should produce a single build artifact. Now, while these are core assumptions, there are ways around them, and I’ve even seen people go to extreme lengths in an attempt to preserve this single, monolithic project. You can create an elaborate set of profiles to modify the build depending on the context in which it is run, and you can attach extra build artifacts to a project using assemblies. Even though Maven makes assumptions about code layout and project structure, it can do just about anything, and in this case, it can be used to approximate the monolithic, combined Ant project. If you do this, if you try to trick Maven the first thing you’ll notice is that your monolithic project’s POM is going to be somewhat unwieldy: it is going to be massive. Instead of a simple, declarative picture of a project, you are going to have a POM that contains multiple assembly definitions. Each assembly definition is going to have to explicitly define the structure of your build artifacts and you are going to find yourself venturing into includes and excludes patterns for things like the Maven Compiler plugin. In other words, you are going to have to expend a huge amount of effort to bend Maven to your assumptions. If you do this, you really won’t be using “Maven”. You’ll be using your own interpretation of Maven, and once you go down this road, you are going to start having problems using standard tools designed for Maven. In short, don’t do this. Don’t try to bypass Maven’s approach to modularity with assemblies and profiles. If you do, you are going to find yourself “swimming upstream”, and your first hint is going to be the size and complexity of your POM files. I’ve certainly created some complex POMs in my time, but I only need to do this for projects that really require customization because they are doing something unique (see the POMs for the Maven book builds, they are large and extremely customized). If you are creating web applications, EARs, and simple Java applications you shouldn’t have large POMs. If you do, it is probably a sign that you have ventured too far “off the map”. While you might be building your project with “Maven”, there is likely something wrong with your approach. If you find yourself constantly challenging an assumption as basic as project modularity, then you need to either rethink using Maven entirely or rethink your project structure. Adopting Maven Means Adopting Modular Structure If you are going to adopt Maven, you must adopt a modular project structure. If you don’t you will be fighting an uphill battle with Maven and the tools that have been designed to work with it. You will be fighting not only with Maven, but you’ll be doing constant battle with your IDE and your repository manager. If you are moving from Ant to Maven, do you yourself a favor. Adopt a modular project structure. Don’t approach Maven as a “toolbox” like Ant with tasks and targets. Approach Maven as a framework with expectations and assumptions. If you do this, you’ll have a much easier time adopting the tool. From http://www.sonatype.com/people/2010/08/how-to-migrate-from-ant-to-maven-project-structure/
August 25, 2010
by Tim O'brien
· 27,698 Views · 1 Like
article thumbnail
Infinite scroll : Loading Content While Scrolling, Using Java and JQuery
Have you seen the infinite scrolling of content in some web pages? For example, in DZone.com when you scroll the page to the bottom, new links will be loaded automatically and it’ll give you the illusion that the page scrolls infinitely. Another good example is that Bing’s Image Search. The technique is not hard to implement. With the use of a single servlet and JSP, we can implement a basic functionality with infinite scroll. Before dive into code details, have a look at this demo to get a feel of it: Infinite Scroll Demo To implement this, we need a servlet which will serve the dynamic content and a JSP file which will have the UI and act as a client to receive the content. Below are the code for these two files. I’m leaving other common stuffs (like web.xml entry etc) to you. Code for Servlet: package com.vraa.demo; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class InfinitContentServlet extends HttpServlet { private static Integer counter = 1; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); try { String resp = ""; for (int i = 1; i <= 10; i++) { resp += "" + counter++ + " This is the dynamic content served freshly from server"; } out.write(resp); } finally { out.close(); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } } Code for JSP file: Demo page: Infinite Scroll with Java and JQuery This page is a demo for loading new content while scrolling. Credits: Veera Sundar | veerasundar.com | @vraa 1Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ornare facilisis mollis. Etiam non sem massa, a gravida nunc. Mauris lectus augue, posuere at viverra sed, dignissim sed libero. 2Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ornare facilisis mollis. Etiam non sem massa, a gravida nunc. Mauris lectus augue, posuere at viverra sed, dignissim sed libero. 3Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ornare facilisis mollis. Etiam non sem massa, a gravida nunc. Mauris lectus augue, posuere at viverra sed, dignissim sed libero. 4Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ornare facilisis mollis. Etiam non sem massa, a gravida nunc. Mauris lectus augue, posuere at viverra sed, dignissim sed libero. 5Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris ornare facilisis mollis. Etiam non sem massa, a gravida nunc. Mauris lectus augue, posuere at viverra sed, dignissim sed libero. How it works? The secret behind this is the scrolltop property. By checking this value we can determine whether the scrollbar has reached near to the bottom or not. If it reached, send an AJAX request to server to get more content and append it to the page. Look at the following two lines which does this: $contentLoadTriggered = false; $("#content-box").scroll(function(){ if($("#content-box").scrollTop() >= ($("#content-wrapper").height() - $("#content-box").height()) && $contentLoadTriggered == false) { $contentLoadTriggered = true; $.get("infinitContentServlet", function(data){ $("#content-wrapper").append(data); $contentLoadTriggered = false; }); } }); From http://veerasundar.com/blog/2010/07/infinite-scroll-loading-content-while-scrolling-using-java-and-jquery/
August 12, 2010
by Veera Sundar
· 38,143 Views
article thumbnail
Unselect all Toggle Buttons of a Group
It’s summer and since I’m hearing more and more the sound of waves splashing instead of the sound of keyboards typing, I’m providing you with quick tricks instead of well-thought deep articles. This time, it’s about Swing. I’m doing Swing for a pet project… a lot. And I’m more of a web guy. So, I’m always butting my head against the wall trying to overcome problem people more experienced in Swing wouldn’t find a problem at all. This is good, since it teaches me another way too think (I as a web developer am not so much event-based, but it is coming to a change with frameworks such as Vaadin or standards like CDI). This said, my latest problem was the following. Most of the time, the toggle buttons are radio buttons: you programmatically select one radio before screen display and since all radios are in the same ButtonGroup, when the user selects one, it deselects the one previously selected. This is good but what if my default state would be that no radio be selected? In fact, to always select a radio means the default state should be displayed as a radio like the others. In my project, I want the default state to be no radio selected, but keep the classical behaviour where selecting a radio means deselecting the one before. Using Swing default classes, it doesn’t work, even if you replace the radio buttons by toggle buttons: when one is selected, it stays selected. Looking at the ButtonGroup code, one understands why: public void setSelected(ButtonModel m, boolean b) { if (b && m != null && m != selection) { ButtonModel oldSelection = selection; selection = m; if (oldSelection != null) { oldSelection.setSelected(false); } m.setSelected(true); } } The classical ButtonGroup only manages when the state goes from unselected to selected! This is cool when using radio buttons, not so with toggle buttons. In order to potentially have no selected buttons in your group, use the following class instead of ButtonGroup: public class NoneSelectedButtonGroup extends ButtonGroup { @Override public void setSelected(ButtonModel model, boolean selected) { if (selected) { super.setSelected(model, selected); } else { clearSelection(); } } } Note: clearSelection() is available only since Java 6 From http://blog.frankel.ch/unselect-all-toggle-buttons-of-a-group
August 10, 2010
by Nicolas Fränkel
· 30,229 Views
article thumbnail
File Copy in Java – Benchmark
Yesterday I wondered if the copyFile method in JTheque Utils was the best method or if I need to change. So I decided to do a benchmark. So I searched all the methods to copy a File in Java, even the bad ones and found the following methods : Naive Streams Copy : Open two streams, one to read, one to write and transfer the content byte by byte. Naive Readers Copy : Open two readers, one to read, one to write and transfer the content character by character. Buffered Streams Copy : Same as the first but using buffered streams instead of simple streams. Buffered Readers Copy : Same as the second but using buffered readers instead of simple readers. Custom Buffer Stream Copy : Same as the first but reading the file not byte by byte but using a simple byte array as buffer. Custom Buffer Reader Copy : Same as the fifth but using a Reader instead of a stream. Custom Buffer Buffered Stream Copy : Same as the fifth but using buffered streams. Custom Buffer Buffered Reader Copy : Same as the sixth but using buffered readers. NIO Buffer Copy : Using NIO Channel and using a ByteBuffer to make the transfer. NIO Transfer Copy : Using NIO Channel and direct transfer from one channel to other. I think, this is the ten principal methods to copy a file to another file. The different methods are available at the end of the post. Pay attention that the methods with Readers only works with text files because Readers are using character by character reading so it doesn’t work on a binary file like an image. Here I used a buffer size of 4096 bytes. Of course, use a higher value improve the performances of custom buffer strategies. For the benchmark, I made the tests using different files. Little file (5 KB) Medium file (50 KB) Big file (5 MB) Fat file (50 MB) And I made the tests first using text files and then using binary files. The source file is not on the same hard disk as the target file. I used a benchmark framework, described here, to make the tests of all the methods. The tests have been made on my personal computer (Ubuntu 10.04 64 bits, Intel Core 2 Duo 3.16 GHz, 6 Go DDR2, SATA Hard Disks). And after a long time of bench, here are the results : Little Text File - All results We see that the method with a simple stream (Naive Streams) is from far the slowest followed by the simple readers methods (Naive Readers). The readers method is a lot faster than the simple stream because FileReader use a buffer internally. To see what happens to the other, here are the same graph but without the first two methods : Little Text File - Best results The best two versions are the Buffered Streams and Buffered Readers. Here this is because the buffered streams and readers can write the file in only one operation. Here the times are in microseconds, so there is really little differences between the methods. So the results are not really relevant. Now, let’s test with a bigger file. Medium Text File We can see that the versions with the Readers are a little slower than the version with the streams. This is because Readers works on character and for every read() operation, a char conversion must be made, and the same conversion must be made on the other side. Another observation is that the custom buffer strategy is faster than the buffering of the streams and than using custom buffer with a buffered stream or a single stream doesn’t change anything. The same observation can be made using the custom buffer using readers, it’s the same with buffered readers or not. This is logical, because with custom buffer we made 4096 (size of the buffer) times less invocations to the read method and because we ask for a complete buffer we have not a lot of I/O operations. So the buffer of the streams (or the readers) is not useful here. The NIO buffer strategy is almost equivalent to custom buffer. And the direct transfer using NIO is here slower than the custom buffer methods. I think this is because here the cost of invoking native methods in the operating system level is higher than simply the cost of making the file copy. Big Text File - All results Here we see that the Naive Readers shows its limit when the file size if growing. So let’s concentrate us on the best methods only, namely, remove the Naive Readers : Big Text File - Best results Here, it’s now clear that the custom buffer strategy is a better than the simple buffered streams or readers and that using custom buffer and buffered streams is really useful for bigger files. The Custom Buffer Readers method is better than Custom Buffer Streams because FileReader use a buffer internally. And now, continue with a bigger file : Fat Text File Results You can see that it doesn’t take 500 ms to copy a 50 MB file using the custom buffer strategy and that it even doesn’t take 400 ms with the NIO Transfer method. Really quick isn’t it ? We can see that for a big file, the NIO Transfer start to show an advantage, we’ll better see that in the binary file benchmarks. We will directly start with a big file (5 MB) for this benchmark : Big Binary File Results So we can make the same conclusion as for the text files, of course, the buffered streams methods is not fast. The other methods are really close. Fat Binary File Results We see here again that the NIO Transfer is gaining advantages more the files is bigger. And just for the pleasure, a great file (1.3 GB) : Enormous Binary File Results We see that all the methods are really close, but the NIO Transfer method has an advantage of 500 ms. It’s not negligible. Conclusion In conclusion, the NIO Transfer method is the best one for big files but it’s not the fastest for little files (< 5 MB). But the custom buffer strategy (and the NIO Buffer too) are also really fast methods to take files. So perhaps, the best method is a method that make a custom buffer strategy on the little files and a NIO Transfer on the big ones. But it will be interesting to also make the tests on an other computer and operating system. We can take several rules from this benchmark : Never made a copy of file byte by byte (or char by char) Prefer a buffer in your side more than in the stream to make less invocations of the read method, but don’t forget the buffer in the side of the streams Pay attention to the size of the buffers Don’t use char conversion if you only need to tranfer the content of a file Don’t hesitate to use channels to make file transfer, it’s the fastest way to make a file transfer I’ve also made some tests, but not complete, for files in the same hard disk and here the NIO Transfer method is a lot faster than the other. I think this is because on the same disk this method can make better use of the filesystem cache. I hope this benchmark (and its results) interested you. Here are the sources of the benchmark : Java Benchmark of File Copy methods From http://www.baptiste-wicht.com/2010/08/file-copy-in-java-benchmark
August 8, 2010
by Baptiste Wicht
· 27,697 Views
article thumbnail
Code Generation With Xtext
Recently I attended a local rheinJUG meeting in Düsseldorf. While the topic of the session was Eclipse e4, the night’s sponsor itemis provided some handouts on Xtext which got me very interested. The reason is that currently at work we are developing a mobile Java application (J9, CDC/Foundation 1.1 on Windows CE6) for which we needed an easy to use and reliable way for configuring navigation through the application. In a previous iteration we had – mostly because of time constraints – hard coded most of the navigational paths, but this time the app is more complex and doing that again was not really an option. First we thought about an XML based configuration, but this seemed to be a hassle to write (and read) and also would mean we would have to pay the price of parsing it on every application startup. Enter Xtext: An Eclipse based framework/library for building text based DSLs. In short, you just provide a grammar description of a new DSL to suit your needs and with – literally – just a few mouse clicks you are provided with a content-assist, syntax-highlight, outline-view-enabled Eclipse editor and optionally a code generator based on that language. Getting started: Sample Grammar There is a nice tutorial provided as part of the Xtext documentation, but I believe it might be beneficial to provide another example of how to put a DSL to good use. I will not go into every step in great detail, because setting up Xtext is Eclipse 3.6 Helios is just a matter of putting an Update Site URL in, and the New Project wizard provided makes the initial setup a snap. I assume, you have already set up Eclipse and Xtext and created a new Xtext project including a generator project (activate the corresponding checkbox when going through the wizard). In this post I am assuming a project name of com.danielschneller.navi.dsl and a file extension of .navi. When finished we will have the infrastructure ready for editing, parsing and generating code based on files like these: navigation rules for MyApplication mappings { map permission AdminPermission to "privAdmin" map permission DataAccessPermission to "privData" map coordinate Login to "com.danielschneller.myapp.gui.login.LoginController" in "com.danielschneller.myapp.login" map coordinate LoginFailed to "com.danielschneller.myapp.gui.login.LoginFailedController" in "com.danielschneller.myapp.login" map coordinate MainMenu to "com.danielschneller.myapp.gui.menu.MainMenuController" in "com.danielschneller.myapp.menu" map coordinate UserAdministration to "com.danielschneller.myapp.gui.admin.UserAdminController" in "com.danielschneller.myapp.admin" map coordinate DataLookup to "com.danielschneller.myapp.gui.lookup.LookupController" in "com.danielschneller.myapp.lookup" } navigations { define navigation USER_LOGON_FAILED define navigation USER_LOGON_SUCCESS define navigation OK define navigation BACK define navigation ADMIN define navigation DATA_LOOKUP } navrules { from Login on navigation USER_LOGON_FAILED go to LoginFailed on navigation USER_LOGON_SUCCESS go to MainMenu from LoginFailed on navigation OK go to Login from MainMenu on navigation ADMIN go to UserAdministration with AdminPermission on navigation DATA_LOOKUP go to DataLookup with DataAccessPermission from UserAdministration on navigation BACK go to MainMenu from DataLookup on navigation BACK go to MainMenu } As you can see it is a nice little language for defining coordinates in an application, meaning a specific GUI for a certain task and the possible navigation paths between them. Optionally a navigation path can be tagged to require one or more permissions to work. So for example one possible navigation path shown in the above sample is from the applications main menu, identified by the identifier MainMenu and represented in code by the com.danielschneller.myapp.gui.menu.MainMenuController class in the com.danielschneller.myapp.menu OSGi bundle to a GUI identified as DataLookup, implemented by com.danielschneller.myapp.gui.lookup.LookupController in the com.danielschneller.myapp.lookup bundle. For this path to be taken, the application must request the DataLookup navigation path and the currently logged in user be assigned the DataAccessPermission. What exactly that means is not the focus of this tutorial, suffice it to say that we somehow need to get the information contained in this specialized language into our Java application in some shape or form that can be evaluated at runtime. In the following example all information will be transformed into a HashMap based data structure. For our little mobile application this has several advantages over the XML option mentioned earlier: No XML parsing necessary on application startup, saving some performance Validation of the navigation rules ahead of time, preventing parse errors at runtime No libraries needed to access the information – by putting everything in a simple HashMap we do not have to rely on any non-standard classes whatsoever First thing I did when I started with Xtext was define a sample input file such as the one above. Then – following its general structure – I began to extract a formal grammar for it. Of course, the first draft of the sample data was not perfect, over the course of a few iterations I refined some of the syntax, but in the end this is the grammar definition I came up with. It is heavily commented to allow you to copy it out and still leave the documentation intact: grammar com.danielschneller.navi.NavigationRules with org.eclipse.xtext.common.Terminals generate navigationRules "http://com.danielschneller/fw/funkmde/navi/NavigationRules" /* * The top level entry point for the file. * "Root" is just a name as good as any, but * makes the meaning quite clear. */ Root: // first thing in the file is a "keyword", // followed by an attribute that will be // accessible as "name" later and allow // definition of an ID type of thing. 'navigation rules for' name=ID // after the keyword and "name" attribute // three sections follow, each assigned // to an attribute for later reference // (called "mappingdefs", "transitiondefs" // and "ruledefs"). // Their types are defined later in the file. mappingsdefs=Mappings transitiondefs=TransitionDefinitions ruledefs=NavigationRules // semicolon ends the definition of "Root" ; // mappings section >>>>>>>>>>>>>>>>>>>>>>>>>>>>> /* * Definition of the "Mappings" type used in * the "Root" type. */ Mappings: // first the keyword "mappings" is expected, // then an open curly 'mappings' '{' // after that a collection of "Mapping"s is // expected. The "+=" means that they will // all be collected in a collection type element // called "mappings" for future reference. // The "+" at the end means "at least one, but // more is just fine". (mappings+=Mapping)+ // finally the "Mappings" type requires a closing // curly brace. '}' // semicolon ends the definition of "Mappings" ; /* * Definition of a single "Mapping", those we are * collecting in the "mappings" attribute of the * "Mappings" type. */ Mapping: // each mapping starts with the keyword "map" // and is followed by an element of type "MappingSpec" 'map' MappingSpec ; /* * Definition of a "MappingSpec" element. This is * actually just a "parent type" for two more specific * kinds of "MappingSpec": */ MappingSpec: // no keywords are defined here, a "MappingSpec" // can be either a "PermissionMappingSpec" or a // "CoordinateMappingSpec". Any of these will be // fine where a "MappingSpec" is asked for. PermissionMappingSpec | CoordinateMappingSpec ; /* * Definition of a "PermissionMappingSpec" element. */ PermissionMappingSpec: // first the keyword "permission" is required. // then a "name" attribute is expected of type ID. // Following the name the "to" keyword is expected, // followed by a string that is stored in the "value" // attribute 'permission' name=ID 'to' value=STRING ; /* * Definition of a "CoordinateMappingSpec" element. * The definition is very similar to the "PermissionMappingSpec" * but has more attributes. */ CoordinateMappingSpec: // first the keyword "coordinate", then an ID stored as "name", // the keyword "to", followed by a string stored as "controllername", // next the keyword "in" and finally another string, memorized as // "bundleid" 'coordinate' name=ID 'to' controllername=STRING 'in' bundleid=STRING ; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< mappings section // >>>>>>>>>>>>>>>>>>>>>>>>>>>>> navigations section /* * Definition of the "TransitionDefinitions" type used in * the "Root" type. */ TransitionDefinitions: // first, this element is introduced with the "navigations" // keyword, followed by an open curly brace. 'navigations' '{' // after that a collection of "TransitionDefinition"s is // expected. The "+=" means that they will // all be collected in a collection type element // called "transitions" for future reference. // The "+" at the end means "at least one, but // more is just fine". (transitions+=TransitionDefinition)+ // the element ends with a closing curly brace '}' ; /* * Definition of a "TransitionDefinition" element. This * one is very simple. */ TransitionDefinition: // the keyword "define navigation" is required first, // then a "name" attribute of type ID is expected. 'define navigation' name=ID ; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< navigations section // >>>>>>>>>>>>>>>>>>>>>>>>>>>>> navrules section /* * Definition of the "NavigationRules" element. */ NavigationRules: // Element starts with the keywords "navrules" and // open curly. 'navrules' '{' // collection attribute called "rules", consisting // of one or more occurrences of a "Rule" element. (rules+=Rule)+ // element finishes with a closing curly keyword '}' ; /* * Definition of a "Rule" element as used in the "NavigationRules" * element. */ Rule: // first the "from" keyword, then a reference to one of the // coordinate mappings defined earlier. This time no new // definition of a coordinate is required, but one of those // that have been listed before. So the type here is put in // square brackets 'from' source=[CoordinateMappingSpec] // following the source specification, one or more "Destination" // type elements are expected, collected in a collection attribute // named "destinations" (destinations+=Destination)+ ; /* * Definition of a "Destination" type. These are collected * in a "Rule". */ Destination: // first comes an "on navigation" keyword. After that a // reference to one of the Transition elements defined // in the "navigations" section is required and stored // in the "transition" attribute. // after that follows a "go to" keyword and a reference // to a coordinate mapping, stored in the "target" attribute. // finally - as with the "destinations" collection attribute // in the "Rule" element - a "permissions" collection is // defined to store none or more (*) "PermissionReference" // elements. 'on navigation' transition=[TransitionDefinition] 'go to' target=[CoordinateMappingSpec] (permissions+=PermissionReference)* ; /* * Definition of a "PermissionReference" type. This is used * in the "permissions" collection of a "Destination". */ PermissionReference: // first, a "with" keyword is expected. After that a // "permission" attribute stores a reference to one of // the previously defined permission mappings from the // "mappings" section. 'with' permission=[PermissionMappingSpec] ; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< navrules section This is what XText can digest and create an editor plugin and outline view for. Just save this as navigationRules.xtext – when you created the XText project in Eclipse using the wizard it should have been prepared for you. Copying and pasting this into a .xtext file in Eclipse will provide you with syntax highlighting, code completion and syntax checking, making it easy to play around with grammar files. Once done, right click the .mwe2 file lying next to the grammar file in the Package Explorer view and select Run As MWE2 Workflow from the context menu. This will take a moment and generate several classes, both in the current (XText) project and the accompanying ...ui project. Next, right click the Xtext project and select Run As Eclipse Application from the context menu. This will bring up another Eclipse instance with the newly created support for navigation rules files (with a .navi suffix) installed. To try it out, just create a new project and in that a new file. Make sure its name ends in .navi. When asked, make sure to accept adding the Xtext nature to the project. You will be presented with a new, empty editor that already has an error marker in it. This is because according to our grammar definition, an empty file does not comply to all the rules we specified. Try hitting the code-completion shortcut (Ctrl-Space) twice and see what happens: The first code-completion fills in the navigation rules for part. According to the grammar this is the only valid text at the beginning of a file, so it is automatically inserted. Hitting Ctrl-Space again will tell you that now you need a Name of type ID. Just go ahead and try out the completion. It will help you create a syntactically sound navigation rules file. Notice that the Problems View tells you what is currently wrong. Also notice, that one you reach a part where references are expected by the grammar (e. g. when defining source and destination coordinates in a navigation rule) you will get suggestions based on what you entered earlier. This is what the whole sample from above looks like in the editor: While you are still fleshing out and fine tuning your grammar definitions, you will probably close this Eclipse instance and reopen it, once you repeated the Run As MWE2 Workflow steps in the main instance. In the long run I suggest you create a Feature and an Update Site project to allow easier distribution and updates of the intermediate iterations. Generating Code Now, as we have a complete Xtext DSL defined and in place let’s have a look at the Code Generation side of things. This part is completely optional: You are free to include the necessary Xtext libraries into your applications runtime (although they seem to be numerous) and just use them to dynamically load and parse .navi files on-the-fly. This would probably be a good idea if you were writing an Eclipse based application anyway. However, when targeting a very limited platform like JavaME this option is not viable. Instead we will now create a code generator that provides a transformation from the DSL syntax into more classic Java terms – specifically we will create a HashMap based data structure that carries all the same information, but in Java terms. This is a sample of what the generated output is going to look like: public class NaviRules { private Map navigationRules = new Hashtable(); // ... public NaviRules() { NaviDestination naviDest; // ========== From Login (com.danielschneller.myapp.gui.login.LoginController) // ========== On USER_LOGON_FAILED // ========== To LoginFailed (com.danielschneller.myapp.gui.login.LoginFailedController in com.danielschneller.myapp.login) naviDest = new NaviDestination(); naviDest.action = "USER_LOGON_FAILED"; naviDest.targetClassname = "com.danielschneller.myapp.gui.login.LoginFailedController"; naviDest.targetBundleId = "com.danielschneller.myapp.login"; store("com.danielschneller.myapp.gui.login.LoginController", naviDest); // ========== On USER_LOGON_SUCCESS // ========== To MainMenu (com.danielschneller.myapp.gui.menu.MainMenuController in com.danielschneller.myapp.menu) naviDest = new NaviDestination(); naviDest.action = "USER_LOGON_SUCCESS"; naviDest.targetClassname = "com.danielschneller.myapp.gui.menu.MainMenuController"; naviDest.targetBundleId = "com.danielschneller.myapp.menu"; store("com.danielschneller.myapp.gui.login.LoginController", naviDest); // ============================================================================= // ========== From LoginFailed (com.danielschneller.myapp.gui.login.LoginFailedController) // ========== On OK // ========== To Login (com.danielschneller.myapp.gui.login.LoginController in com.danielschneller.myapp.login) naviDest = new NaviDestination(); naviDest.action = "OK"; naviDest.targetClassname = "com.danielschneller.myapp.gui.login.LoginController"; naviDest.targetBundleId = "com.danielschneller.myapp.login"; store("com.danielschneller.myapp.gui.login.LoginFailedController", naviDest); // .... and so on ... } } The support class NaviDestination is omitted but is generally just a value holder struct type class. When creating the Xtext project using the wizard earlier we created a third Eclipse project, ending in ...generator. Its src folder contains three subdirectories called model, templates and workflow. Put the sample .navi file into the model directory. It will serve as the input for the generator. Create the first template Code generation is based on templates. Xtext leverages the Xpand template engine. In the templates directory create a new Xpand template using the context menu. Call it NaviRules.xpt, open it and insert the following: «REM» import the namespace defined in our DSL model «ENDREM» «IMPORT navigationRules» «REM» Define a template called "main" for elements of type "Root". The minus sign at the end takes care of not adding a newline at the end of it. «ENDREM» «DEFINE main FOR Root-» «ENDDEFINE» As there is only one instance of a Root element in a navigation rules file, this will be the main entry point - hence the name. There is no need to call it main, but it seems fitting. Now between the DEFINE and ENDDEFINE insert what is to be generated: As shown above, we need a new Java source file called NaviRules.java: ... «DEFINE main FOR Root-» «FILE "NaviRules.java"-» «ENDFILE-» «ENDDEFINE» ... Again, the contents to be generated is put in between the FILE and ENDFILE brackets. Anything not enclosed in «» will be used verbatim in the output file. So first of all, put in the static parts of the Java file. What I did was first write the source for a single navigation rule by hand, made sure it compiled and then copied over the relevant parts into the template piece by piece: ... «FILE "NaviRules.java"-» import java.util.*; public class NaviRules { public static class NaviDestination { String action; List requiredPermissions = new ArrayList(); String targetClassname; String targetBundleId; NaviDestination() {}; public final List getRequiredPermissions() { return new ArrayList(requiredPermissions); } // let Eclipse generate getters, setters, // equals and hashCode methods for this } private Map navigationRules = new Hashtable(); «ENDFILE-» ... Now, this is nothing special so far. To fill in the elements from the navigation rules DSL file put in the following: ... private Map navigationRules = new Hashtable(); public NaviRules() { NaviDestination naviDest; «REM» Iterate all elements in the "rules" collection attribute of the "ruledefs" attribute of the "Root" element. Call each iterated element (which is of type "Rule") "rule" and expand the "ruletmpl" template for it here. «ENDREM» «FOREACH ruledefs.rules AS r»«EXPAND ruletmpl FOR r»«ENDFOREACH» } ... In the class constructor we first define a local variable naviDest of the previously declared type. Then - as the comment states - the FOREACH instruction will iterate over all Rule type elements. This might not seem to be completely obvious at first. Remember at this point in the template the current scope is the "Root" element from the navigation rules file. It has an attribute called ruledefs as per the grammer definition. This attribute is of type NavigationRules which in turn has a collection attribute called rules, containing of Rule type objects. Inside the loop the current element can then be adressed by the template variable name r. The loop body (between FOREACH and ENDFOREACH) contains another Xpand instruction to expand a template called ruletmpl which will be declared next. Don't worry, even though this is a little difficult at first - switching contexts between the Java and the template scopes is made significantly easier in Eclipse, because the Xpand template editor will syntax color (static parts are blue) and also assist you with code completion inside the Xpand template parts. Ctrl-Spacing your way through it will make things more obvious than they are when reading an example. Now for the ruletmpl template. Place it below the ENDDEFINE statement belonging to the main template: ... «ENDFILE-» «ENDDEFINE» «DEFINE ruletmpl FOR Rule-» // ========== From «source.name» («source.controllername») «FOREACH destinations AS d»«EXPAND destTmpl(source) FOR d»«ENDFOREACH» // ============================================================================= «ENDDEFINE» You see the same idea used again: Static parts that get transferred into the output file 1:1 and Xpand statements that fill in data from the navigation rules definition file. In this case you see references to the attributes of the Rule element. As per the FOREACH instruction in the previous template, the one at hand will be repeated for every instance of Rule in our source file. Inside this definition the current scope is that of Rule, so with «source.name» the name attribute of the CoordinateMappingSpec object referenced as source in a Rule is taken first, then the controllername attribute likewise. Next up another FOREACH loop iterates the one or more possible Destinations of each Rule. Instead of just applying a template (destTmpl) for every Destination we also pass in the corresponding CoordinateMappingSpec stored in the source attribute of the Rule. This is then used in the following template: ... «DEFINE destTmpl(CoordinateMappingSpec source) FOR Destination-» // ========== On «transition.name» // ========== To «target.name» («target.controllername» in «target.bundleid») naviDest = new NaviDestination(); naviDest.action = "«transition.name»"; naviDest.targetClassname = "«target.controllername»"; naviDest.targetBundleId = "«target.bundleid»"; «FOREACH permissions AS p»«EXPAND permTmpl FOR p»«ENDFOREACH» store("«source.controllername»", naviDest); «ENDDEFINE» «DEFINE permTmpl FOR PermissionReference-» naviDest.requiredPermissions.add("«permission.value»"); «ENDDEFINE» In this innermost templates the attributes of the CoordinateMappingSpec objects source and target are accessed and put into place to be assigned to the members a NaviDestination Java object instance per Destination. There is only one more (very simple) template for the PermissionReference elements. With this, the Xpand file is complete. Set Up The Generator Workflow The wizard initially created a NavigationRulesGenerator.mwe2 file in the workflow folder. Open it and replace its contents with the following: module workflow.NavigationRulesGenerator import org.eclipse.emf.mwe.utils.* var targetDir = "src-gen" var fileEncoding = "Cp1252" var modelPath = "src/model" Workflow { component = org.eclipse.xtext.mwe.Reader { path = modelPath // this class has been generated by the xtext generator register = com.danielschneller.navi.NavigationRulesStandaloneSetup {} load = { slot = "root" type = "Root" } } component = org.eclipse.xpand2.Generator { metaModel = org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel {} expand = "templates::NaviRules::main FOREACH root" outlet = { path = targetDir } fileEncoding = fileEncoding } } The most interesting parts of this workflow file are the load section in the Reader component and the expand and outlet sections in the Generator component: The first one will connect a so-called slot with the Root element from our navigation rules. The second one will trigger the evaluation of the main template in the NaviRules.xpt file in the templates folder and feed any Root instances it finds in the *.navi files from the src/model (modelPath) into it. Now it is time for some actual generation. Run the generator workflow Right click the MWE2 file you just edited and select the Run As MWE2 Workflow command from the context menu. The Eclipse console will show this output: 0 [main] DEBUG org.eclipse.xtext.mwe.Reader - Resource Pathes : [src/model] 431 [main] DEBUG xt.validation.ResourceValidatorImpl - Syntax check OK! Resource: file:/Users/ds/ws/ws36_xtext/com.danielschneller.navi.dsl.generator/src/model/MyApp.navi 1013 [main] INFO org.eclipse.xpand2.Generator - Written 1 files to outlet [default](src-gen) 1014 [main] INFO .emf.mwe2.runtime.workflow.Workflow - Done. Then have a look at the newly generated contents of the src-gen source folder. If everything went alright, you should find a fresh NaviRules.java file placed there, based on the contents of your navigation rules file and the Xpand templates. Try and make some changes to the template, then re-run the workflow. You will see the changes reflected in the generated source file. Generate a second source File In the templates directory add another Xpand template file Navigation.xpt with the following content: «IMPORT navigationRules»; «DEFINE main FOR Root-» «FILE "Navigation.java"-» public final class Navigation { «FOREACH ruledefs.rules.destinations.transition.collect(e|e.name).toSet().sortBy(e|e) AS t»«EXPAND actionTmpl FOR t»«ENDFOREACH» private final String name; private Navigation(String aName) { name = aName; } public String getName() { return name; } } «ENDFILE-» «ENDDEFINE» «DEFINE actionTmpl FOR String-» /** Constant for Navigation «this» */ public static final Navigation «this» = new Navigation("«this»"); «ENDDEFINE» This is a template for a type-safe enumeration that can be used in Java 1.4 - remember I had to do this for JavaME. Notice the FOREACH loop in this case. It demonstrates that not only simple iterations are possible, but that Xpand allows more complex operations as well. In this case it will collect the names of all the navigation transitions from all the Destinations in the navigation rules. These are of type String. They are made unique by converting them to a Set datastructure and then finally sorted in their natural order. The resulting list of sorted strings is then iterated, each one - called t - is passed to the actionTmpl template. It is very simple, just placing the string itself («this») into a single line of Java source code. Of course, strictly speaking this is a rather complicated procedure to get the same information we could also have taken from the TransitionDefinitions element in the rules definition. However I think it serves as a nice example for additional Xpand capabilities. For a full description of its possibilities, have a look at the Xpand Reference in the Eclipse documentation. To use the new template, add another section to the MWE2 workflow definition: component = org.eclipse.xpand2.Generator { metaModel = org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel {} expand = "templates::Navigation::main FOREACH root" outlet = { path = targetDir } fileEncoding = fileEncoding } Running it again will produce a slightly different output, making clear that two files have been generated. This is what comes out in the src-gen folder as Navigation.java: public final class Navigation { /** Constant for Navigation ADMIN */ public static final Navigation ADMIN = new Navigation("ADMIN"); /** Constant for Navigation BACK */ public static final Navigation BACK = new Navigation("BACK"); /** Constant for Navigation DATA_LOOKUP */ public static final Navigation DATA_LOOKUP = new Navigation("DATA_LOOKUP"); /** Constant for Navigation OK */ public static final Navigation OK = new Navigation("OK"); ... More... This was just about my first experiments with Xtext. I am sure there is plenty more to be done with it. For more reading, please have a look at this very nice Getting started with Xtext tutorial by Peter Friese of Itemis. From http://www.danielschneller.com/2010/08/code-generation-with-xtext.html
August 7, 2010
by Daniel Schneller
· 27,163 Views
article thumbnail
Optimizing JPA Performance: An EclipseLink, Hibernate, and OpenJPA Comparison
'Impedance mismatch'. No two words encompass the troubles, headaches and quirks most developers face when attempting to link applications to relational databases (RDBMS). But lets face it, object orientated designs aren't going away anytime soon from mainstream languages and neither are the relational storage systems used in most applications. One side works with objects, while the other with tables. Resolving these differences -- or as its technically referred to 'object/relational impedance mismatch' -- can result in substantial overhead, which in turn can materialize into poor application performance. In Java, the Java Persistence API (JPA) is one of the most popular mechanisms used to bridge the gap between objects (i.e. the Java language) and tables (i.e. relational databases). Though there are other mechanisms that allow Java applications to interact with relational databases -- such as JDBC and JDO -- JPA has gained wider adoption due to its underpinnings: Object Relational Mapping (ORM). ORM's gain in popularity is due precisely to it being specifically designed to address the interaction between object and tables. In the case of JPA, there is a standard body charged with setting its course, a process which has given way to several JPA implementations, among the three most popular you will find: EclipseLink (evolved from TopLink), Hibernate and OpenJPA. But even though all three are based on the same standard, ORM being such a deep and complex topic, beyond core functionality each implementation has differences ranging from configuration to optimization techniques. What I will do next is explain a series of topics related to optimizing an application's use of the JPA, using and comparing each of the previous JPA implementations. While JPA is capable of automatically creating relational tables and can work with a series of relational database vendors, I will part from having pre-existing data deployed on a MySQL relational database, in addition to relying on the Spring framework to facilitate the use of the JPA. This will not only make it a fairer comparison, but also make the described techniques appealing to a wider audience, since performance issues become a serious concern once you have a large volume of data, in addition to MySQL and Spring being a common choice due to their community driven (i.e. open-source) roots. See the source code/application section at the end for instructions on setting up the application code discussed in the remainder of the sections. Download the Source Code associated with this article (~45 MB) The basics: Metrics In order to establish JPA performance levels in an application, it's vital to first obtain a series of metrics related to a JPA implementation's inner workings. These include things like: What are the actual queries being performed against a RDBMS? How long does each query take? Are queries being performed constantly against the RDBMS or is a cache being used? These metrics will be critical to our performance analysis, since they will shed light on the underlying operations performed by a JPA implementation and in the process show the effectiveness or ineffectiveness of certain techniques. In this area you will find the first differences among implementations, and I'm not talking about metric results, but actually how to obtain these metrics. To kick things off, I will first address the topic of logging. By default, all three JPA implementations discussed here -- EclipseLink, Hibernate and OpenJPA -- log the query performed against a RDBMS, which will be an advantage in determining if the queries performed by an ORM are optimal for a particular relational data model. Nevertheless, tweaking the logging level of a JPA implementation further can be helpful for one of two things: Getting even more details from the underlying operations made by a JPA -- which can be turned off by default (e.g. database connection details) -- or getting no logging information at all -- which can benefit a production system's performance. Logging in JPA implementations is managed through one of several logging frameworks, such as Apache Commons Logging or Log4J. This requires the presence of such libraries in an application. Logging configuration of a JPA implementation is mostly done through a value in an application's persistence.xml file or in some cases, directly in a logging framework's configuration files. The following table describes JPA logging configuration parameters: Large table, so here's an external link In addition to the information obtained through logging, there is another set of JPA performance metrics which require different steps to be obtained. One of these metrics is the time it takes to perform a query. Even though some JPA implementations provide this information using certain configurations, some do not. Even so, I opted to use a separate approach and apply it to all three JPA implementations in question. After all, time metrics measured in milliseconds can be skewed in certain ways depending on start and end time criteria. So to measure query times, I will use Aspects with the aid of the Spring framework. Aspects will allow us to measure the time it takes a method containing a query to be executed, without mixing the timing logic with the actual query logic -- the last feature of which is the whole purpose of using Aspects. Further discussing Aspects would go beyond the scope of performance, so next I will concentrate on the Aspect itself. I advise you to look over the accompanying source code, Aspects and Spring Aspects for more details on these topics and their configuration. The following Aspect is used for measuring execution times in query methods. package com.webforefront.aop;import org.apache.commons.lang.time.StopWatch;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.annotation.Aspect;@Aspectpublic class DAOInterceptor { private Log log = LogFactory.getLog(DAOInterceptor.class); @Around("execution(* com.webforefront.jpa.service..*.*(..))") public Object logQueryTimes(ProceedingJoinPoint pjp) throws Throwable { StopWatch stopWatch = new StopWatch(); stopWatch.start(); Object retVal = pjp.proceed(); stopWatch.stop(); String str = pjp.getTarget().toString(); log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": " + stopWatch.getTime() + "ms"); return retVal; } The main part of the Aspect is the @Around annotation. The value assigned to this last annotation indicates to execute the aspect method -- logQueryTimes -- each time a method belonging to a class in the com.webforefront.jpa.service package is executed -- this last package is where all our application's JPA query methods will reside. The logic performed by the logQueryTimes aspect method is tasked with calculating the execution time and outputting it as logging information using Apache Commons Logging. Another set of important JPA metrics is related to statistics beyond those provided by standard logging. The statistics I'm referring to are things related to caches, sessions and transactions. Since the JPA standard doesn't dictate any particular approach to statistics, each JPA implementation also varies in the type and way it collects statistics. Both Hibernate and OpenJPA have their own statistics class, where as EclipseLink relies on a Profiler to gather similar metrics. Since I'm already relying on Aspects, I will also use an Aspect to obtain statistics both prior and after the execution of a JPA query method. The following Aspect obtains statistics for an application relying on Hibernate. package com.webforefront.aop;import org.hibernate.stat.Statistics;import org.hibernate.SessionFactory;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.beans.factory.annotation.Autowired;import javax.persistence.EntityManagerFactory;import org.hibernate.ejb.HibernateEntityManagerFactory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;@Aspectpublic class CacheHibernateInterceptor { private Log log = LogFactory.getLog(DAOInterceptor.class); @Autowired private EntityManagerFactory entityManagerFactory; @Around("execution(* com.webforefront.jpa.service..*.*(..))") public Object log(ProceedingJoinPoint pjp) throws Throwable { HibernateEntityManagerFactory hbmanagerfactory = (HibernateEntityManagerFactory) entityManagerFactory; SessionFactory sessionFactory = hbmanagerfactory.getSessionFactory(); Statistics statistics = sessionFactory.getStatistics(); String str = pjp.getTarget().toString(); statistics.setStatisticsEnabled(true); log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (Before call) " + statistics); Object result = pjp.proceed(); log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (After call) " + statistics); return result; } } Notice the similar structure to the prior timing Aspect, except in this case the logging output contains values that belong to the Statistics Hibernate class obtained via the application's EntityManagerFactory. The next Aspect is used to obtain statistics for an application relying on OpenJPA. package com.webforefront.aop;import org.apache.openjpa.datacache.CacheStatistics;import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;import org.apache.openjpa.persistence.OpenJPAPersistence;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.beans.factory.annotation.Autowired;import javax.persistence.EntityManagerFactory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;@Aspectpublic class CacheOpenJPAInterceptor { private Log log = LogFactory.getLog(DAOInterceptor.class); @Autowired private EntityManagerFactory entityManagerFactory; @Around("execution(* com.webforefront.jpa.service..*.*(..))") public Object log(ProceedingJoinPoint pjp) throws Throwable { OpenJPAEntityManagerFactory ojpamanagerfactory = OpenJPAPersistence.cast(entityManagerFactory); CacheStatistics statistics = ojpamanagerfactory.getStoreCache().getStatistics(); String str = pjp.getTarget().toString(); log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (Before call) Statistics [start time=" + statistics.start() + ",read count=" + statistics.getReadCount() + ",hit count=" + statistics.getHitCount() +",write count=" + statistics.getWriteCount() + ",total read count=" + statistics.getTotalReadCount() + ",total hit count=" + statistics.getTotalHitCount() +",total write count=" + statistics.getTotalWriteCount()); Object result = pjp.proceed(); log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (After call) Statistics [start time=" + statistics.start() + ",read count=" + statistics.getReadCount() + ",hit count=" + statistics.getHitCount() +",write count=" + statistics.getWriteCount() + ",total read count=" + statistics.getTotalReadCount() + ",total hit count=" + statistics.getTotalHitCount() +",total write count=" + statistics.getTotalWriteCount()); return result; } } Once again, notice the similar Aspect structure to the previous Aspect which relies on an application's EntityManagerFactory. In this case, the logging output contains values that belong to the CacheStatistics OpenJPA class. Since OpenJPA does not enable statistics by default, you will need to add the following two properties to an application's persistence.xml file: The first property ensures statistics are gathered, while the second property is used to indicate the gathering of statistics take place on a single JVM. NOTE: The value "true(EnableStatistics=true)" also enables caching in addition to statistics. Since EclipseLink doesn't have any particular statistics class and relies on a Profiler to determine advanced metrics, the simplest way to obtain similar statistics to those of Hibernate and OpenJPA is through the Profiler itself. To active EclipseLink's Profiler you just need to add the following property to an application's persistence.xml file: . By doing so, the EclipseLink Profiler output's several metrics on each JPA query method execution as logging information. Now that you know how to obtain several metrics from all three JPA implementations and understand they will be obtained as fairly as possible for all three providers, it's time to put each JPA implementation to the test along with several performance techniques. JPQL queries, weaving and class transformations Lets start by making a query that retrieves data belonging to a pre-existing RDBMS table named "Master". The "Master" table contains over 17,000 records belonging to baseball players. To simplify matters, I will create a Java class named "Player" and map it to the "Master" table in order to retrieve the records as objects. Next, relying on the Spring framework's JpaTemplate functionality, I will setup a query to retrieve all "Player" objects, with the query taking the following form: getJpaTemplate().find("select e from Player e"); See the accompanying source code for more details on this last process. Next, I deploy the application using each of the three JPA implementations on Apache Tomcat, doing so separately, as well as starting and stopping the server on each deployment to ensure fair results. These are the results of doing so on a 64-bit Ubuntu-4GB RAM box, using Java 1.6: All player objects - 17,468 records Time Query Hibernate 3558 ms select player0_.lahmanID as lahmanID0_, player0_.nameFirst as nameFirst0_, player0_.nameLast as nameLast0_ from Master player0_ EclipseLink (Run-time weaver - Spring ReflectiveLoadTimeWeaver weaver ) 3215 ms SELECT lahmanID, nameLast, nameFirst FROM Master EclipseLink (Build-time weaving) 3571 ms SELECT lahmanID, nameLast, nameFirst FROM Master EclipseLink (No weaving) 3996 ms SELECT lahmanID, nameLast, nameFirst FROM Master OpenJPA (Build-time enhanced classes) 5998 ms SELECT t0.lahmanID, t0.nameFirst, t0.nameLast FROM Master t0 OpenJPA (Run-time enhanced classes- OpenJPA enhancer) 6136 ms SELECT t0.lahmanID, t0.nameFirst, t0.nameLast FROM Master t0 OpenJPA (Non enhanced classes) 7677 ms SELECT t0.lahmanID, t0.nameFirst, t0.nameLast FROM Master t0 As you can observe, the queries performed by each JPA implementation are fairly similar, with two of them using a shortcut notation (e.g. t0 and player0 for the table named 'Master'). This syntax variation though has minimal impact on performance, since directly querying an RDBMS using any of these notation variations shows identical results. However, the query times made through several JPA implementations using distinct parameters vary considerably. One important factor leading to this time difference is due to how each implementation handles JPA entities. Lets start with the OpenJPA implementation which had the poorest times. OpenJPA can execute an enhancement process on Java entities (e.g. in this case the 'Player' class). This enhancement process can be performed when the entities are built, at run-time or foregone altogether. As you can observe, foregoing entity enhancement altogether in OpenJPA produced the longest query times. Where as enhancing entities at either build-time or run-time produced relatively better results, with the former beating out the latter. By default, OpenJPA expects entities to be enhanced. This means you will either need to explicitly configure an application to support unenhanced classes by adding the following: ...property to an application's persistence.xml file or enhance classes at build-time or at run-time relying on the OpenJPA enhancer, otherwise an application relying on OpenJPA will throw an error. Given these OpenJPA results, the remaining OpenJPA tests will be based on build-time enhanced entity classes. For more on the topic of OpenJPA enhancement, refer to the OpenJPA documentation in addition to consulting the accompanying source code for this article. You may be wondering what exactly constitutes OpenJPA enhancement ? OpenJPA entity enhancement is a processing step applied to the bytecode generated by the Java compiler which adds JPA specific instructions to provide optimal runtime performance, these instructions can include things like flexible lazy loading and dirty read tracking. So why doesn't Hibernate or EclipseLink enhance entities ? In short, Hibernate and EclipseLink also enhance JPA entites, they just don't outright call it 'enhancement'. EclipseLink calls this 'enhancement' process by the more technical term: weaving. Similar to OpenJPA's enhancement process, weaving in EclipseLink can take place at either build-time (a.k.a. static weaving), run-time or forgone altogether. As you can observe in the results, all of EclipseLink's tests present smaller variations compared to OpenJPA. The longest EclipseLink variation involved not using weaving. If you think about it, this is rather logical given that the purpose of weaving consists of altering Java byte code for the purpose of adding optimized JPA instructions that include lazy loading, change tracking, fetch groups and internal optimizations. For the EclipseLink tests using weaving, both build-time and run-time weaving present better results. For build-time weaving, I used EclipseLink's library along with an Apache Ant task, where as for run-time weaving, I used the Spring framework's ReflectiveLoadTimeWeaver. I can only assume the slightly better performance of using run-time weaving over build-time weaving in EclipseLink was due to the fact of using a weaver integrated with the Spring framework, which in turn could result in better JPA optimizations designed for Spring applications. Nevertheless, considering the test result of forgoing weaving altogether, weaving does not appear to be a major performance impact when using EclipseLink, ceteris paribus. By default, EclipseLink expects run-time weaving to be enabled, otherwise you will receive an error in the form 'Cannot apply class transformer without LoadTimeWeaver specified'. This means that for cases using build-time weaving or no weaving at all, you will need to explicitly indicate this behavior. In order to disable EclipseLink weaving you will need to either configure an application's EntityManagerFactory Spring bean with: ... or add the .... ...property to an application's persistence.xml file. To indicate an application's entities are built using build-time weaving, substitute the previous property's "false" value with "static". To configure the default run-time weaver expected by EclipseLink, add the following: ...property to an application's EntityManagerFactory Spring bean. Given these EclipseLink results, the remaining EclipseLink tests will be based on run-time weaving provided by the Spring framework. For more on the topic of EclipseLink weaving, refer to the EclipseLink documentation at http://wiki.eclipse.org/Introduction_to_EclipseLink_Application_Development_(ELUG)#Using_Weaving, in addition to consulting the accompanying source code for this article. Hibernate doesn't require neither enhancing JPA entities or weaving. For this reason, there is only one test result. This not only makes Hibernate simpler to setup, but judging by its only test result -- which clock's in at second place with respect to all other tests -- Hibernate's performance ranks high compared to its counterparts. However, in what I would consider Hibernate's equivalent to OpenJPA's enhancement process or EclipseLink's weaving, you will find a series of Hibernate properties. For example, Hibernate has properties such as hibernate.default_batch_fetch_size designed to optimize lazy loading. As you might recall, among the purposes of both OpenJPA's enhancement process and EclipseLink's weaving are the optimization of lazy loading. So where as OpenJPA and EclipseLink require a separate and monolithic step -- at build-time or run-time -- to achieve JPA optimization techniques, Hibernate falls back to the use of granular properties specified in an application's persistence.xml file. Nevertheless, given that Hibernate's default behavior proved to be on par with the best query times, I didn't feel a need to further explore with these Hibernate properties. To get another sense of the times and mapping procedures of each JPA implementation, I will make more selective queries based on a Player object's first name and last name. These are the results of performing a query for all Player objects whose first name is John and a query for all Player objects whose last name in Smith. All player objects whose first name is John - 472 records Time Query EclipseLink 1265 ms SELECT lahmanID, nameLast, nameFirst FROM Master WHERE (nameFirst = ?) Hibernate 613 ms select player0_.lahmanID as lahmanID0_, player0_.nameFirst as nameFirst0_, player0_.nameLast as nameLast0_ from Master player0_ where player0_.nameFirst=? OpenJPA 1643 ms SELECT t0.lahmanID, t0.nameFirst, t0.nameLast FROM Master t0 WHERE (t0.nameFirst = ?) [params=?] All player objects whose last name is Smith - 146 records Time Query EclipseLink 986 ms SELECT lahmanID, nameLast, nameFirst FROM Master WHERE (nameLastt = ?) Hibernate 537 ms select player0_.lahmanID as lahmanID0_, player0_.nameFirst as nameFirst0_, player0_.nameLast as nameLast0_ from Master player0_ where player0_.nameLast=? OpenJPA 1452 ms SELECT t0.lahmanID, t0.nameFirst, t0.nameLast FROM Master t0 WHERE (t0.nameLast = ?) [params=?] These test results tell a slightly different story,with all three JPA implementations presenting substantial time differences amongst one another. At a lower record count, Hibernate's out-of-the-box configuration resulted in almost twice as fast queries as its closest competitor and almost three times faster queries than its other competitor. To get an even broader sense of the times and mapping procedures of each JPA implementation, I will make a query on a single Player object based on its id. These are the results of performing such a query. Single player object whose ID is 777- 1 record Time Query EclipseLink 521 ms SELECT lahmanID, nameLast, nameFirst FROM Master WHERE (lahmanID = ?) Hibernate 157 ms select player0_.lahmanID as lahmanID0_0_, player0_.nameFirst as nameFirst0_0_, player0_.nameLast as nameLast0_0_ from Master player0_ where player0_.lahmanID=? OpenJPA 1052 ms SELECT t0.nameFirst, t0.nameLast FROM Master t0 WHERE t0.lahmanID = ? [params=?] With the exception of the faster query times -- due to it being a query for a single Player object -- the times between JPA implementations are practically in proportion to the queries used for extracting multiple Player objects by first and last name. This will do it as far as test queries are concerned. However, a word of caution is in order when discussing these topics on optimization/enhancement/weaving. Even though the previous tests consisted of querying over 17,000 records and confirm clear advantages of using one provider and technique over another, they are still one dimensional, since they're based on read operations performed on a single object type and a single RDBMS table. JPA can perform a large array of operations that also include updating, writing and deleting RDBMS records, not to mention the execution of more elaborate queries that can span multiple objects and tables. In addition, RDBMS themselves can have influencing factors (e.g. indexes) over JPA query times. So all this said, it's not too far fetched to think the use of OpenJPA entity enhancement, EclipseLink weaving or Hibernate properties, could have varying degrees -- either beneficial or detrimental -- depending on the queries (i.e. multi-table, multi-object) and type of JPA operation (i.e. read, write, update, delete) involved. Next, I will describe one of the most popular techniques used to boost performance in JPA applications. Caches A cache allows data to remain closer to an application's tier without constantly polling an RDBMS for the same data. I entitled the section in plural -- caches -- because there can be several caches involved in an application using JPA. This of course doesn't mean you have to configure or use all the caches provided by an application relying on JPA, but properly configuring caches can go a long way toward enhancing an application's JPA performance. So lets start by analyzing what it's each JPA implementation offers in its out-of-the-box state in terms of caching. The following table illustrates tests done by simply invoking the previous JPA queries for a second and third consecutive time, without stopping the server. Note that the same process of deploying a single application at once was used, in addition to the server being re-started on each set of tests. Query / Implementation EclipseLink Hibernate OpenJPA All records (1st time) 3215 ms 3558 ms 5998 ms All records (2nd time) 507 ms 272 ms 521 ms All records (3rd time) 439 ms 218 ms 263 ms First name (1st time) 1265 ms 613 ms 1643 ms First name (2nd time) 151 ms 115 ms 239 ms First name (3rd time) 154 ms 101 ms 227 ms Last name (1st time) 986 ms 537 ms 1452 ms Last name (2nd time) 41 ms 41 ms 112 ms Last name (3rd time) 65 ms 38 ms 117 ms By ID (1st time) 521 ms 157 ms 1052 ms By ID (2nd time) 1 ms 6 ms 3 ms By ID (3rd time) 1 ms 3 ms 3 ms As you can observe, on both the second and third invocation all the queries show substantial improvements with respect to the first invocation. The primary cause for these improvements is unequivocally due to the use of a cache. But what type of cache exactly ? Could it be an RDBMS's own caching engine ? JPA ? Spring ? Or some other variation ?. In order to shed some light on cache usage, the following table illustrates the cache statistics generated on each of the previous JPA queries. Query / Impleme)ntation EclipseLink Hibernate OpenJPA All records (2nd time) number of objects=17468, total time=506, local time=506, row fetch=65, object building=328, cache=112, sql execute=47, objects/second=34521, sessions opened=2, sessions closed=2, connections obtained=2, statements prepared=2, statements closed=2, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=34936, queries executed to database=2, query cache puts=0, query cache hits=0, query cache misses=0 N/A All records (3rd time) number of objects=17468, total time=435, local time=435, profiling time=1, row fetch=28, object building=323, cache=106, logging=1, sql execute=27, objects/second=40156, sessions opened=3, sessions closed=3, connections obtained=3, statements prepared=3, statements closed=3, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=52404, queries executed to database=3, query cache puts=0, query cache hits=0, query cache misses=0 N/A First name (2nd time) number of objects=472, total time=148, local time=148, row fetch=27, object building=106, cache=7, logging=1, sql execute=3, objects/second=3189, sessions opened=2, sessions closed=2, connections obtained=2, statements prepared=2, statements closed=2, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=944, queries executed to database=2, query cache puts=0, query cache hits=0, query cache misses=0 N/A First name (3rd time) number of objects=472, total time=152, local time=152, row fetch=20, object building=121, cache=7, sql execute=3, objects/second=3105, sessions opened=3, sessions closed=3 connections obtained=3, statements prepared=3, statements closed=3, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=1416, queries executed to database=3, query cache puts=0, query cache hits=0, query cache misses=0 N/A Last name (2nd time) number of objects=146, total time=40, local time=40, row fetch=7, object building=27, cache=2, logging=1, sql execute=3, objects/second=3650, sessions opened=2, sessions closed=2, connections obtained=2, statements prepared=2, statements closed=2, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=292, queries executed to database=2, query cache puts=0, query cache hits=0, query cache misses=0 N/A Last name (3rd time) number of objects=146, total time=63, local time=63, profiling time=1, row fetch=6, object building=19, cache=5, sql prepare=1, sql execute=23, objects/second=2317, sessions opened=3, sessions closed=3, connections obtained=3, statements prepared=3, statements closed=3, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=438 queries executed to database=3, query cache puts=0, query cache hits=0, query cache misses=0 N/A By ID (2nd time) number of objects=1, total time=1, local time=1, time/object=1, objects/second=1000, sessions opened=2, sessions closed=2, connections obtained=2, statements prepared=2, statements closed=2, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=2, queries executed to database=0, query cache puts=0, query cache hits=0, query cache misses=0 N/A By ID (3rd time) number of objects=1, total time=1, local time=1, time/object=1, objects/second=1000, sessions opened=3, sessions closed=3, connections obtained=3, statements prepared=3, statements closed=3, second level cache puts=0, second level cache hits=0, second level cache misses=0, entities loaded=3, queries executed to database=0, query cache puts=0, query cache hits=0, query cache misses=0 N/A Notice the statistics generated by each JPA implementation are different. EclipseLink reports a single cache statistic, OpenJPA doesn't even report statistics unless a cache is enabled -- see previous section on metrics for details on this behavior -- and Hibernate reports two cache related statistics: second level cache and query cache. At this juncture, if you look at the test results and statistics for the second and third invocation, something won't add up. How is it that OpenJPA's test results came out faster when caching is disabled by default ? An how about Hibernate returning 0's on its cache related statistics, even when its test results came out faster ? The reason for this performance increase is due to RDBMS caching. On the first query, the RDBMS needs to read data from its own file system (i.e. perform an I/O operation), on subsequent requests the data is present in RDBMS memory (i.e. its cache) making the entire JPA query much faster. A closer look at the Hibernate statistics field 'queries executed to the database' can confirm this. Notice that on every second query it shows 2 and on every third query it shows 3, meaning the data was read directly from the database. NOTE: The only exception to this occurs when a query is made on a single entity (i.e. by id), I will address this shortly. Next, lets start breaking down the caches you will encounter when using JPA applications. The JPA 2.0 standard defines two types of caches: A first level cache and a second level cache. The first level cache or EntityManager cache is used to properly handle JPA transactions. A first level cache only exist for the duration of the EntityManager. With the exception of long lived operations performed against a RDBMS, JPA EntityManager's are short lived and are created & destroyed per request or per transaction. In this case, given the nature of the queries, first level caches are cleared on every query. A second level cache on the other hand is a broader cache that can be used across transactions and users. This makes a JPA second level cache more powerful, since it can avoid constantly polling an RDBMS for the same data. But even though the JPA 2.0 standard now addresses second level cache features, this was not the case in JPA 1.0. In the 1.0 version of the JPA standard only a first level cache was addressed, leaving the door completely open on the topic of a second level cache. This created a fragmented approach to caching in JPA implementations, which even now as JPA 2.0 compliant implementations emerge, some non-standard features continue to be part of certain implementations given the value they provide to JPA caching in general. So as I move forward, bear in mind that just like previous JPA topics, each JPA implementation can have its own particular way of dealing with second level caching. I will start with OpenJPA, which has the least amount of proprietary caching options. To enable OpenJPA caching (i.e. second level caching) you need to declare the following two properties in an application's persistence.xml file: The first property ensures caching and statistics are activated, while the second property is used to indicate caching take place on a single JVM. The following results and statistics were obtained with OpenJPA's second level cache enabled. Query with OpenJPA caching Time Statistics Time without statistics All records (2nd time) 420 ms read count=34936, hit count=17468, write count=17468, total read count=34936, total hit count=17468, total write count=17468 347 ms All records (3rd time) 254 ms read count=52404, hit count=34936, write count=17468, total read count=52404, total hit count=34936, total write count=17468 230 ms First name (2nd time) 125 ms read count=944, hit count=472, write count=472, total read count=944, total hit count=472, total write count=472 127 ms First name (3rd time) 114 ms read count=1416, hit count=944, write count=472, total read count=1416, total hit count=944, total write count=472 132 ms Last name (2nd time) 63 ms read count=292, hit count=146, write count=146, total read count=292, total hit count=146, total write count=146 53 ms Last name (3rd time) 49 ms read count=438, hit count=292, write count=146, total read count=438, total hit count=292, total write count=146 50 ms By ID (2nd time) 5 ms read count=2, hit count=1, write count=1, total read count=2, total hit count=1, total write count=1 1 ms By ID (3rd time) 4 ms read count=3, hit count=2, write count=1, total read count=3, total hit count=2, total write count=1 1 ms As these test results illustrate, executing subsequent JPA queries with OpenJPA's second level cache produce superior results. Another important behavior illustrated in some of these test cases is that by simply disabling statistics -- and still using the second level cache -- query times improve even more. The OpenJPA statistics also demonstrate how the cache is being used. Notice that on each subsequent query the statistics field 'hit count' is duplicated, which means data is being read from the cache (i.e. a hit). Also notice the statistics field 'write count' remains static, which means data is only written once from the RDBMS to the cache. This is pretty basic functionality for a second level cache. On certain occasions a need may arise to interact directly with a cache. These interactions can range from prohibiting an entity from being cached, assigning a particular amount of memory to a cache, forcing an entity to always be cached, flushing all the data contained in a cache, or even plugging-in a third party caching solution to provide a more robust strategy, among other things. The JPA 2.0 standard provides a very basic feature set in terms of second level caching through javax.persistence.Cache. Upon consulting this interface, you'll realize it only provides four methods charged with verifying the presence of entities and evicting them. This feature set not only proves to be limited, but also cumbersome since it can only be leveraged programmatically (i.e. through an API). In this sense, and as I've already mentioned, JPA implementations have provided a series of features ranging from persistence.xml properties to Java annotations related to second level caching. OpenJPA offers several of these second level caching features, including a separate and supplemental cache called a 'query cache' which can further improve JPA performance. For such cases, I will point you directly to OpenJPA's cache documentation available at http://openjpa.apache.org/builds/apache-openjpa-2.1.0-SNAPSHOT/docs/manual/ref_guide_caching.html#ref_guide_cache_query so you can try these parameters for yourself on the accompanying application source code. Hibernate just like OpenJPA has its second level cache disabled. To enable Hibernate's second level cache you need to add the following properties to an application's persistence.xml file: Its worth mentioning that Hibernate has integral support for other second level caches. The previous properties displayed how to enable the HashtableCacheProvider cache -- the simplest of the integral second level caches -- but Hibernate also provides support for five additional caches, which include: EHCache, OSCache, SwarmCache, JBoss cache 1 and JBoss cache 2, all of which provide distinct features, albeit require additional configuration. Besides these properties, Hibernate also requires that each JPA entity be declared with a caching strategy. In this case, since the Person entity is read only, a caching strategy like the following would be used: Similar to OpenJPA, Hibernate also offers several second level caching features through proprietary annotations and configurations, as well as support for the separate and supplemental cache called a 'query cache' which can further improve JPA performance. For such cases, I will also point you directly to Hibernate's cache documentation available at http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-cache so you can try these parameters for yourself on the accompanying application source code. Unlike OpenJPA and Hibernate, EclipseLink's second level cache is enabled by default, therefore there is no need to provide any additional configuration. However, similar to its counterparts, EclipseLink also has a series of proprietary second level cache features which can enhance JPA performance. You can find more information on these features by consulting EclipseLink's cache documentation available at: http://wiki.eclipse.org/Introduction_to_Cache_(ELUG) With this we bring our discussion on object relational mapping performance with JPA to a close. I hope you found the various tests and metrics presented here a helpful aid in making decisions about your own JPA applications. In addition, don't forget you can rely on the accompanying source code to try out several JPA variations more ad-hoc to your circumstances. About the author Daniel Rubio is an independent technology consultant specializing in enterprise and web-based software. He blogs regularly on these and other software areas at http://www.webforefront.com. He's also authored and co-authored three books on Java technology. Source code/Application installation * Install MySQL on your workstation (Tested on MySQL 5.1.37-64 bits) - http://dev.mysql.com/downloads/ * Install data set on MySQL - Go to http://www.baseball-databank.org/ and click on the link titled 'Database in MySQL form'. This will download a zipped file with a series of MySQL data structures containing baseball statistics. First create a MySQL database to host the data using the command: 'mysqladmin -p create jpaperformance'. This will create a database named 'jpaperformance'. Next, load the baseball statistics using the following command: 'mysql -p -D jpaperformance < BDB-sql-2009-11-25.sql' where 'BDB-sql-2009-11.25.sql' represents the unzipped SQL script obtained by extracting the zip file you dowloaded. * Create JPA application WARs - The download includes source code, library dependencies and an Ant build file. This includes all three JPA implementations Hibernate 3.5.3, EclipseLink 2.1 and OpenJPA 2.1. To build the JPA Hibernate WAR - ant hibernate To build the JPA EclipseLink WAR - ant eclipselink To build the JPA OpenJPA WAR - ant openjpa All builds are placed under the dist/ directories. * Deploy to Tomcat 6.0.26 - Copy the MySQL Java driver and Spring Tomcat Weaver -- included in the download directory 'tomcat_jar_deps' -- to Apache Tomcat's /lib directory. - Copy each JPA application WAR to Apache Tomcat's /webapps directory, as needed. * Deployment URL's http://localhost:8080/hibernate/hibernate/home ( Query all Player objects ) http://localhost:8080/eclipselink/eclipselink/home ( Query all Player objects ) http://localhost:8080/openjpa/openjpa/home ( Query all Player objects ) http://localhost:8080/hibernate/hibernate/firstname/ ( Query Player objects by first name) http://localhost:8080/eclipselink/eclipselink/firstname/ ( Query Player objects by first name) http://localhost:8080/openjpa/openjpa/firstname/ ( Query Player objects by first name) http://localhost:8080/hibernate/hibernate/lastname/ ( Query Player objects by last name) http://localhost:8080/eclipselink/eclipselink/lastname/ ( Query Player objects by last name) http://localhost:8080/openjpa/openjpa/lastname/ ( Query Player objects by last name) http://localhost:8080/hibernate/hibernate/playerid/ (Query Player by id) http://localhost:8080/eclipselink/eclipselink/playerid/ ( Query Player by id) http://localhost:8080/openjpa/openjpa/playerid/ ( Query Player by id)
July 20, 2010
by Daniel Rubio
· 153,843 Views · 2 Likes
article thumbnail
Running JUnit tests in Parallel with Maven
A little-known but very useful feature slipped into JUnit 4 and recent versions of the Maven Surefire Plugin: support for parallel testing.
July 7, 2010
by John Ferguson Smart
· 57,155 Views · 1 Like
article thumbnail
NeoLoad 3.1 load tests Java Serialization
Neotys, a leader in easy-to-use, cost effective load testing tools for web applications today announced NeoLoad 3.1, the first test solution on the market to incorporate support for new push technologies such as Adobe RTMP or Ajax Push and now supports Java serialization. A new Java serialization module has been added to record and replay applications using the Java object serialization over HTTP. This module is fully compatible with the spring remote framework. New features Push Technologies module RTMP module Java Serialization module Advanced variabilization Alerts thresholds Customized reports > View all the new features. Free Trial Download the NeoLoad v3.1 demo (30-day free trial). More information http://www.neotys.com
June 18, 2010
by Christophe Marton
· 1,333 Views
article thumbnail
Builder Pattern Tutorial with Java Examples
Learn the Builder Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
June 15, 2010
by James Sugrue
· 92,380 Views · 14 Likes
article thumbnail
State Pattern Tutorial with Java Examples
Learn the State Design Pattern with easy Java source code examples as James Sugrue continues his design patterns tutorial series, Design Patterns Uncovered
June 9, 2010
by James Sugrue
· 138,765 Views · 17 Likes
  • Previous
  • ...
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×