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 DevOps and CI/CD Topics

article thumbnail
Implementing Retries with a MDB or an MQ Batch Job? (WAS 7, MQ 6)
Both approaches have some advantages and disadvantages and so it’s a question of the likelihood of particular problems and business requirements and priorities.
November 10, 2010
by Jakub Holý
· 27,265 Views
article thumbnail
Naming Conventions for Parameterized Types
Parameterized types - the <> expressions that can be used in Java as of JDK 5 are not just for collections. I find myself frequently using them in APIs I design. They really do let you write things which are more generic in the non-Java sense of the word - and the result is more reusable code, which means less code overall, which means fewer bugs and things to test. The verbosity, and some of the weirdness of type-erasure are less than ideal, but used right, the benefits are worth the complexity. The standard (and somewhere recommended) naming convention for parameterized types is to use a single-letter name. That works fine in signatures that have only one such type. But in practice, single-letter names make code less self-describing, and if you're defining a class with more than one parameterized type, it can be confusing and hard to read. People other than me will have to call, understand and maintain my code - the more self-describing I can make it, the better. So I am looking for a naming convention that makes it obvious that something is a parameterized type, but allows for descriptive names. I am wondering if anybody else has run into this problem, and if there is any emerging consensus on naming generics. Do you work on a project that uses generics a lot? If so, what do you do? Here's an example. At the moment, I'm writing a generic (in both senses) class which simply limits the number of threads which can access some resource. It's basically a wrapper around a Semaphore which uses a Runnable-like object to ensure that the Semaphore is accessed correctly, and does some non-blocking statistic gathering about thread contention. So to access the scarce resource, you pass in a ResourceAccessor: public interface ResourceAccessor { public Result run (ProtectedResource resource, Argument argument); } The problem is that, when somebody looks at this interface, they will instantly get the idea that there are really classes they need to go find, which are called ProtectedResource, Argument and Result - and of course, no such classes exist - these are just names for generic types. The standard-naming-convention is worse: public interface ResourceAccessor { public S run (T resource, R argument); } Here, nobody could possibly figure out what on earth this class is for without extensive documentation - this is a really horrible idea. So I've concluded that the standard recommendations for generic type names are simply wrong for any non-trivial usage (I.e. Collection is fine, since there is one type and Collections are well-understood). You simply can't do this on a non-collection code structure you have invented, or people will just be confused and not use it. The best suggestion I've heard thus far is using $ as a prefix: public interface ResourceAccessor <$ProtectedResource, $Argument, $Result> { public $Result run ($ProtectedResource resource, $Argument argument); } I don't find this pretty, but I don't have any better ideas, and at least it makes it crystal-clear that there is something different about these names. Any thoughts? What do you do in this situation?
September 20, 2010
by Tim Boudreau
· 17,827 Views
article thumbnail
How to resize an ExtJS Panel, Grid, Component on Window Resize without using Ext.Viewport
This post will walk through how to resize an ExtJS Panel, Grid, Component on Window Resize without using Ext.Viewport. Problem: You have a legacy page and you want to change an html grid for an ExtJS DataGrid, because it has so many cool features. Or you have a page with some design and you are going to use only one ExtJS Component. In both cases, you also want to render your ExtJS Component to a specific DIV. Also, you want you component to be resized in case you resize the browser window. How can you do that if resize a single component in an HTML page it is not the default behavior of an ExtJS Component (except if you use Ext.Viewport)? Solution: Condor (from ExtJS Community Support Team) developed a plugin that can do that for you. I had to spend some time to understand how the plugin works, and I finally got it working as I wanted. Well, I recommend you to spend some time reading this thread: http://www.sencha.com/forum/showthread.php?28318 (if you have any issues or questions, please publish it on the thread, so other members can give you the support you need). Requirements to make the plugin work: Your have to apply the following style to the DIV (the width is up to you, the other styles are mandatory, otherwise it will not work): If you have any border around your ExtJS component, you have to set a HEIGHT. And you will also have to set a height to your ExtJS component. In this case, autoHeight will not work. If you DO NOT have any border or other design on the ExtJS component side, you do not need to set height and you can use autoHeight. In my case, I put a border on the external DIV, so I have to set Height: HTML code (all DIVs): And you need to add the plugin to the component (In this case, I’m using an ExtJS DataGrid): var grid = new Ext.grid.GridPanel({ store: store, columns: [ {header: 'Company', width: 160, sortable: true, dataIndex: 'company'}, {header: 'Price', width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'}, {header: 'Change', width: 75, sortable: true, renderer: change, dataIndex: 'change'}, {header: '% Change', width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'}, {header: 'Last Updated', width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'} ], stripeRows: true, autoExpandColumn: 'company', height: 490, autoWidth:true, title: 'Array Grid', // config options for stateful behavior stateful: true, stateId: 'grid' ,viewConfig:{forceFit:true} ,renderTo: 'reportTabContent' // render the grid to the specified div in the page ,plugins: [new Ext.ux.FitToParent("reportTabContent")] }); And done! Now you can resize the browser and the component will resize itself! I tested it on Firefox, Chrome and IE6. You can download my sample project from my GitHub: http://github.com/loiane/extjs-fit-to-parent PS.: If you want to use the full browser window, use a Viewport. Happy coding!
August 24, 2010
by Loiane Groner
· 48,802 Views
article thumbnail
Getting started with Nexus Maven Repo Manager
This tutorial outlines steps required to install Nexus (Maven Repository Manager) under Tomcat, or another webapp container. It shows you practical configuration and includes code snippets that go in your pom.xml and settings.xml in order to read and publish artifacts to your Nexus server. Step 1: Download Download Nexus from here (at the time of writing, latest is 1.6.0) Step 2: Install Copy the war to TOMCAT_HOME/webapps/nexus.war Though not required, it is a generally good idea to restart tomcat after installing a new war /etc/init.d/tomcat restart /etc/init.d/tomcat restart Step 3: Configure security a) Change default admin password: The default admin username/password is admin/admin123. Login as admin and change the password to a secure password. Login -> [admin, admin123] -> Left Menu -> Security -> Change Password -> click “Change Password” b) Anonymous Access: By default Nexus is open to the public. If you want to secure access to nexus, disable ‘Nexus anonymous user’ Admin -> Left Menu -> Users -> ‘Nexus anonymous user’ -> Status=Disabled c) Deployment user: Change password for deployment user Admin -> Left menu -> Users -> Deployment user -> Change email address Admin -> Left menu -> Users -> Right click on ‘Deployment user’ in the user list -> Set Password -> click ‘Set password’ to finish Step 4: Set SMTP server It is a good idea to configure SMTP server, so that you can receive emails from Nexus. Admin login -> Left menu -> Administration -> Server ->SMTP Settings -> (host localhost, port 25, no login, no password mostly works on a linux machine) Step 5: Change Base Url If you are running Nexus behind Apache using mod_jk or mod_proxy, change your base url here. Admin login -> Left menu -> Administration -> Server -> Application Server Settings -> Base url Step 6: Add a task to periodically remove old snapshots If you or your CI server publishes snapshots to Nexus several times a day, then you should consider adding a task to delete duplicate/old snapshots for the same GAV (group, artifact, version). If you don’t do this, you will notice that the Nexus disk usage will increase with time. Admin login -> Left menu -> Administration -> Scheduled tasks -> Add… -> name=”Remove old snapshots”, Repository/Group=Snapshots (Repo), Minimum Snapshot Count=1, Snapshot Retention(days)=3, Recurrence=Daily, Recurring time=2:00 -> click ‘Save’ Step 7: Using Nexus: reading and publishing artifacts If you want to deploy your artifacts to your Nexus, you need to configure 2 files: pom.xml and settings.xml a) pom.xml – for each project which wishes to publish to Nexus, add your repo to the pom.xml vineetmanohar-nexus vineetmanohar nexus dav:http://nexus.vineetmanohar.com/nexus/content/repositories/releases vineetmanohar-nexus vineetmanohar nexus dav:http://nexus.vineetmanohar.com/nexus/content/repositories/snapshots vineetmanohar-nexus vineetmanohar http://nexus.vineetmanohar.com/nexus/content/groups/public true true vineetmanohar-nexus vineetmanohar http://nexus.vineetmanohar.com/nexus/content/groups/public true true vineetmanohar-nexus vineetmanohar nexus dav:http://nexus.vineetmanohar.com/nexus/content/repositories/releases vineetmanohar-nexus vineetmanohar nexus dav:http://nexus.vineetmanohar.com/nexus/content/repositories/snapshots vineetmanohar-nexus vineetmanohar http://nexus.vineetmanohar.com/nexus/content/groups/public true true vineetmanohar-nexus vineetmanohar http://nexus.vineetmanohar.com/nexus/content/groups/public true true b) settings.xml – If you have disabled anonymous access to Nexus, add the deployment password to your ~/.m2/repository/settings.xml file vineetmanohar-nexus deployment password_goes_here From http://www.vineetmanohar.com/2010/06/getting-started-with-nexus-maven-repo-manager
June 7, 2010
by Vineet Manohar
· 105,095 Views · 3 Likes
article thumbnail
FlexMonkey 4 and FlexMonkium for Selenium
FlexMonkey is a free and open source Adobe AIR application used for testing Flex and AIR based applications. It can record, playback, and verify Flex UI interactions. FlexMonkey also generates ActionScript-based testing scripts that you can easily include within a continuous integration environment. Gorilla Logic is the company that builds FlexMonkey, and its CEO, Stuart Stern, recently spoke with DZone about their launch of FlexMonkey 4, which supports all of the new Spark components in Flex 4. For more info on FlexMonkey, see our interview with Stuart Stern at Adobe Max 2009. DZone: First thing's first. What's new in FlexMonkey 4? Stuart Stern: Before we talk about the updates to FlexMonkey, let me give you a bit of background for those who have not used any of the previous versions. We (Gorilla Logic) built and open sourced the first version of FlexMonkey in late 2008 because we needed a serious Flex testing solution for our enterprise customers. Basically, FlexMonkey allows developers and QA people to create comprehensive tests for their Flex applications by easily recording real interactions with the user interface, and by letting the test creator add verification checks on both data and visual snapshots of the UI. Once the interactions have been recorded the test can be played back through the FlexMonkey console or through generated test code in Fluint / FlexUnit. The generated code can be extended to create complex, data-driven test scenarios, and can be easily run within build and continuous integration environments. In our software consulting engagements, we have found that FlexMonkey reduces the overall numbers of tests that developers need to create, since driving testing from the user interface can exercise the entire application stack, top-to-bottom and even front-to-back. Let’s be clear though, api-level testing and tools like FlexUnit are still an essential part of Flex development, especially in testing non ui components. Where FlexMonkey is a better fit for testing is around visual components, which are difficult, if not impossible, to test as a ‘unit.’ On our typical applications, we tend to end up with about 80% of our developer created tests constructed through FlexMonkey, with the other 20% being created as more traditional unit tests. As far as FlexMonkey 4, the goals were pretty simple; the community has been beating down our door for Spark Component (Flex 4) support. So, we’ve added full support for the new component library recently released by Adobe. This is key for enterprise Flex development projects that have come to depend on FlexMonkey for regression and QA testing, and that are ready to move to Flex 4. We've also simplified the setup for FlexMonkey 4, so it's easier for new users to get up and running quickly. DZone: What were some of the difficulties in implementing support for all of Flex 4's Spark components? Stuart: From a FlexMonkey perspective, there is no difference between Spark and Halo components. However, one of the things that makes FlexMonkey so powerful is that it records "semantic" events such as "open combobox" rather than "click at this screen coordinate". So FlexMonkey needs to "understand" every Flex component, and we had to tell it some new things about the new Spark components and their events. . DZone: Are there any trends your seeing in how developers are using FlexMonkey in their UI design workflow? Stuart: FlexMonkey was initially envisioned as a tool for developers. Because developers test code that is still under development, it is important for a test automation tool to be able to express tests in a largely logical fashion. Tests that are too tied to the precise look of a screen at a particular point in time are two brittle for use by developers. FlexMonkey tests are typically robust across application skinning, since tests can be written independent of the exact positions or styling of the components on the screen, and can pinpoint specific functionality. In this way developers can automate testing of portions of an application even before the UI design is fully finalized. Although we designed it for developer testing, it's ability to record tests automatically, add verification logic by pointing and clicking, and do fuzzy bitmap comparisons on select portions of the screen, make FlexMonkey highly effective for QA testing purposes as well. Additionally, when developers and testers use the same tools, they can share some of the same tests, with QA using developer tests as a starting point, and developers incorporating some QA tests into continuous integration builds. DZone: Tell me about the next tool you'll be focusing on: FlexMonkium. Stuart: FlexMonkium is a plugin for Selenium IDE and Selenium RC. It adds FlexMonkey recording and playback capability to Selenium so you can create tests for applications that mix HTML and Flex. We recently completed development and are now doing final testing and documentation. We expect it make it publicly available any day now. FlexMonkium makes all of FlexMonkey's functionality available within the Selenium IDE, and generates JUnit-based tests that can be run with Selenium RC. DZone: Are there any interesting or exciting things you see down the road for the Flash platform ecosystem? How do you think the platform will fare against emerging UI design technologies like HTML5, CSS3, etc.? Stuart: The recent attacks on the Flash platform by Apple have certainly put the ‘HTML 5 vs. Flash’ battle on everyone’s radar. At Gorilla, we build both native browser applications (HTML 5, etc.) and Flex applications -- and even native iPhone applications -- for our customers. There are pros and cons to each and situations that definitively call for one versus another. Having said that, we are a consulting company that builds serious enterprise software. We embrace Flex because it enables us to do things we cannot do otherwise, and do them quickly. On any given project, we don't ask if we should use Flex, we ask if there is any reason why we can't.
June 4, 2010
by Mitch Pronschinske
· 14,707 Views
article thumbnail
JMS Clustering by Example
It's amazing how the JBoss Team put together an easy way to do JMS Clustering, out of the box!!. I'll start with an easy example, creating a Queue named "MyClusteredQueue". In this example I'm using JBoss AS 5.1. and two computers connected on the same network, with these IP's: - Computer A: 192.168.0.143 - Computer B: 192.168.0.210 So, here are the steps: 1) Install the JBoss on both computers. We are going to use the "all" configuration for both computers. 2) We create our Queue on both servers. Go to $JBOSS_HOME/server/all/deploy/messaging/ and edit the destinations-service.xml file. Add the MyClusteredQueue before the last server tag. It looks like this: jboss.messaging:service=ServerPeer jboss.messaging:service=PostOffice true This is how you add a Queue to the JBoss, and the people how are familiar with this, the only new thing is to add the attribute "Clustered". This step must be set on both computers. At the end of the article you can find the files. 3) Write the MDB to consume the messages, and deploy it on the two computers. (I'm using an EJB 3 - MDB style). import java.net.InetAddress; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.ObjectMessage; import org.apache.log4j.Logger; /** * @author felipeg * */ @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/MyClusteredQueue") }) public class JMSClusterClientHandler implements MessageListener { Logger log = Logger.getLogger(JMSClusterClientHandler.class); @Override public void onMessage(Message message) { try{ if (message instanceof ObjectMessage) { InetAddress addr = InetAddress.getLocalHost(); log.info("########## Processing Host: " + addr.getHostName() + " ##########" ); ObjectMessage objMessage = (ObjectMessage) message; Object obj = objMessage.getObject(); log.info("Object received:" + obj.toString()); } } catch (Exception e) { e.printStackTrace(); } } } 4) Start the jboss with the following options: Computer A: $ cd $JBOSS_HOME/bin $ ./run.sh -c all -b 192.168.0.143 -Djboss.messaging.ServerPeerID=1 Computer B: $ cd $JBOSS_HOME/bin $ ./run.sh -c all -b 192.168.0.210 -Djboss.messaging.ServerPeerID=2 It is necesary to give an ID to each server and this is accomplished with this directive: -Djboss.messaging.ServerPeerID When you start the jboss on computer A, you should see the logs (server.log) telling you that there is one node ready and listening, and once you start the jboss on computer B, on the log will appear the two nodes, the two IP's ready to consume messages. 5) Now it's time to send a Message to the Queue. To accomplish this it's necessary to change the connection factory to "ClusteredConnectionFactory" (JMSDispatcher.java - See the code below). Also on the jndi.properties (if you are using the default InitialContext) file it's necessary to add the two computers ip's separated by comma to the java.naming.provider.url property. (In my case a create a Properties variable and I set all the necessary properties, JMSDispatcher.java - see the code below). java.naming.provider.url=192.168.0.143:1099,192.168.0.210:1099 The client that I wrote is a web application, that consist in one index.jsp page, which contains a form that prompts you for the name of the queue, the type of messaging (Queue or Topic), the server ip and port, how many times it will send the message and the actual message to be sent; also the web application has a Servlet (JMSClusteredClient.java - see code below) that receives the postback and helper class (JMSDispatcher.java - see code below) that sends the message to the jboss servers. You can to deploy it in any computer. In my case I deployed it on the Computer A. And you can access it through this URL: http://192.168.0.143:8080/JMSWeb/ (just modify the IP where the client war was deployed). If you notice (on the index.jsp - code below) I've already put some default values that reflects the name of the Queue, and the IP's of my two computers. Now, If you increment the number of times that the message will be sent (maybe a 10) and fill out the message box, and click "Send" you should see on the two servers some of the messages being consumed by the MDB. Here are the Files to create the client: index.jsp JMS Clustered - Test Client Server: QueueTopic Times:Message: Servlet: JMSClusteredClient.java public class JMSClusteredClient extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response) */ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); String topicqueue = request.getParameter("topicqueue"); String message = request.getParameter("message"); String server = request.getParameter("server"); String messageType = request.getParameter("messageType"); String times = request.getParameter("times"); int intTimes = Integer.parseInt(times); JMSDispatcher dispatcher = new JMSDispatcher(); dispatcher.setTopicQueueName(topicqueue); dispatcher.setServer(server); dispatcher.setMessageType(messageType); try { for(int count =1; count <= intTimes;count++){ dispatcher.sendMessage( count + " of " + times + " " + message); } out.println("Message [" + message + "] sent successfully to [" + topic + "] to the [" + server + "] server " + times + " times."); } catch (JMSException e) { e.printStackTrace(); out.println("Error:" + e.getMessage()); } catch (NamingException e) { out.println("Error:" + e.getMessage()); e.printStackTrace(); } finally{ out.close(); } } } A utility to send the messages: JMSDispatcher.java public class JMSDispatcher { /** * */ private static final long serialVersionUID = 7105145023422143880L; private static Logger log = Logger.getLogger(JMSDispatcher.class); private final String CONNECTION_FACTORY_CLUSTERED = "ClusteredConnectionFactory"; private final String CONNECTION_FACTORY = "ConnectionFactory"; private final String TOPIC = "TOPIC"; private final String QUEUE = "QUEUE"; private String topicQueueName; private String server; private String messageType; public void setTopicQueueName(String value){ this.topicQueueName = value; } public void setServer(String value){ this.server = value; } public void setMessageType(String value){ this.messageType = value; } public void sendMessage(Object objectMessage) throws JMSException, NamingException{ log.debug("##### Setting up a Queue/Topic Message: #####"); if (TOPIC.equals(messageType)){ sendTopicMessage(objectMessage); } else if (QUEUE.equals(messageType)){ sendQueueMessage(objectMessage); } log.debug("##### Publishing Message: Done #####"); } private void sendQueueMessage(Object objectMessage) throws JMSException, NamingException{ try{ InitialContext initialContext = getInitialContext(); QueueConnectionFactory qcf = (QueueConnectionFactory) initialContext.lookup(CONNECTION_FACTORY_CLUSTERED); QueueConnection queueConn = qcf.createQueueConnection(); Queue queue = (Queue) initialContext.lookup(topicQueueName); QueueSession queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueConn.start(); QueueSender send = queueSession.createSender(queue); ObjectMessage om = queueSession.createObjectMessage((Serializable)objectMessage); setMessageProperties(om); log.debug("##### Publishing Message to a Queue: " + queueName + "#####"); send.send(om); send.close(); queueConn.stop(); queueSession.close(); queueConn.close(); }catch(MessageFormatException ex){ log.error("##### The MESSAGE is not Serializable ####"); throw ex; }catch(MessageNotWriteableException ex){ log.error("##### The MESSAGE is not Readable ####"); throw ex; }catch(JMSException ex){ log.error("##### JMS provider fails to set the object due to some internal error. ####"); throw ex; } } private void sendTopicMessage(Object objectMessage) throws JMSException, NamingException{ try{ InitialContext initialContext = getInitialContext(); TopicConnectionFactory tcf = (TopicConnectionFactory)initialContext.lookup(CONNECTION_FACTORY_CLUSTERED); TopicConnection topicConn = tcf.createTopicConnection(); Topic topic = (Topic) initialContext.lookup(topicQueueName); TopicSession topicSession = topicConn.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE); topicConn.start(); TopicPublisher send = topicSession.createPublisher(topic); ObjectMessage om = topicSession.createObjectMessage(); om.setObject((Serializable)objectMessage); setMessageProperties(om); log.debug("##### Publishing Message to a Topic: " + topicName + "#####"); send.publish(om); send.close(); topicConn.stop(); topicSession.close(); topicConn.close(); }catch(MessageFormatException ex){ log.error("##### The MESSAGE is not Serializable ####"); throw ex; }catch(MessageNotWriteableException ex){ log.error("##### The MESSAGE is not Readable ####"); throw ex; }catch(JMSException ex){ log.error("##### JMS provider fails to set the object due to some internal error. ####"); throw ex; } } private InitialContext getInitialContext() throws NamingException{ Properties jboss = new Properties(); jboss.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); jboss.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); jboss.put("java.naming.provider.url", server); return new InitialContext(jboss); } } And the web.xml JMSWeb index.jsp JMSClusteredClient JMSClusteredClient com.blogspot.felipeg48.jms.web.JMSClusteredClient JMSClusteredClient /JMSClusteredClient Happy Clustering!!
May 26, 2010
by Felipe Gutierrez
· 16,728 Views
article thumbnail
Running Hazelcast on a 100 Node Amazon EC2 Cluster
The purpose of this article is to give you the details of our 100 node cluster demo. This demo is recorded and you can watch the 5 minute screencast Hazelcast is an open source clustering and highly scalable data distribution platform for Java. JVMs that are running Hazelcast will dynamically cluster and allow you to easily share and partition your application data across the cluster. Hazelcast is a peer-to-peer solution (there is no master node, every node is a peer) so there is no single point of failure. Communication among cluster members is always TCP/IP with Java NIO beauty. The default configuration comes with 1 backup so if a node fails, no data will be lost (you can specify the backup count). It is as simple as using java.util.{Map, Queue, Set, List}. Just add the hazelcast.jar into your classpath and start coding. When you download the Hazelcast, you will find a test.sh under bin directory. The test.sh runs an application which randomly makes 40% get, 40% put and 20% remove on a distributed map. In this demo the same test application will be used to see how it performs on 100 node cluster. Amazon EC2 and S3 An easy to use and scalable cloud environment was needed for demo so we decided to use Amazon EC2 for server instances (nodes) and S3 service to store demo application zip and configuration files. With its newly announced Java SDK, it is very simple to start/stop server instances and upload files to S3 programatically. Hazelcast AMI & Launcher The challenge here is that we are running an application on 100 nodes and dealing with each and every server in the cluster is a huge task. We don't want to ssh into every server and manually start the application. This part is automated by creating a special server image (AMI). The AMI contains Java Runtime and a launcher application we developed, which will download the demo application from Amazon S3, unzip it, and run the hazelcast/bin/test.sh in it. The Launcher is actually so generic that it can run any application; it doesn't care/know what test.sh contains. Deployer Deployment of the demo application is also automated so that we don't need to login into AWS Management Console and manually start instances. Deployer instantiates any number of Amazon EC2 servers with any AMI and also uploads the demo application zip file to S3. So the idea here is that, the Deployer will store the application into S3 and launch 100 EC2 instances with our image. The Launcher on each instance will download the application from S3 and run it. Demo Details. The smallest EC2 instances (m1.small) are used to run the demo. These are the virtual instances with CPU about 1.0 GHz. Also keep in mind that EC2 platform suffers from considerable amount of network latency. That's why we increased the thread count to 250 in our application. The following steps performed during the demo Download hazelcast-1.8.3.zip from www.hazelcast.com. Unzip the file and move the monitoring war file into tomcat6/webapps directory. Edit the test.sh under the bin directory: Add -Xmx1G -Xms1G Add -Dhazelcast.initial.wait.seconds=100 to make the cluster evenly partition on start so that migration can be avoided for better performance. Add t250 as an argument to the application to set thread count to 250. Remember the latency issue. Run the Deployer from IDE. Check from EC2 Management Console if 100 servers started. Start tomcat. Copy the public DNS name of one of the servers to connect to from monitoring tool. Go to http://localhost:8080/hazelcast-monitor-1.8.3/ (Hazelcast Monitoring Tool). Paste the address and connect to the cluster. Enjoy! Results You should always look for programatic ways of launching applications on the cloud. With these tools we were able to deploy and run the demo application on 100 servers in minutes. The entire Hazelcast cluster was making over 400,000 operations per second on the smallest EC2 instances. In our next demo we will experiment Hazelcast on large data set and even bigger cluster. Watch the screencast
April 16, 2010
by Fuad Malikov
· 62,669 Views · 1 Like
article thumbnail
Pipes and Filters Pattern in .NET
A pipeline in software context is a very well-known architectural style in which a process consists of a series of steps to be followed in order to proceed the data, and the output of one step is the input of another step. This is also called the Pipes and Filters design pattern. The naming comes from the physical pipeline as this architectural style is very similar to a pipeline in which a stream of data comes in and leaves after being processed. The original idea of pipeline in software is implemented in Unix. This pattern is used in many places. Compiler pipeline, ASP.NET HTTP Pipeline, and workflows are three of many examples that I can mention. The pipes and filters style is implemented in various platforms with different techniques and technologies. Recently I was in a situation to implement this pattern and did some research to find more about the possible options to implement this pattern in the .NET Framework. Doing my research, I found many approaches introduced by community members but the most mature technique is the one that Oren Eini has described in his blog post using Generics. There is also an interesting technique described by Jeremy Likness using the yield keyword in C#. In this post I’m going to apply Oren’s approach and expand it to write a simple implementation of the classic KWIC example in Software Engineering. I liked Oren’s code because as he said, it’s comparatively simpler than other solutions introduced for this problem in the .NET Framework. An Overview of KWIC KWIC stands for Key Word in Context and is a classic problem in Software Engineering papers in which you try to create an index of words by sorting and aligning each word in a piece of text. David Parnas has a famous paper on modularity that uses KWIC as an example. There are some basic and advanced implementations of KWIC in different platforms but the main steps are: Reading the input Shifting the words in each line to get a new permutation Sorting the results Writing the output Interestingly, in this case the output of each step is the input of the next step which makes this a good candidate for the Pipes and Filters pattern. Implement the Pipes and Filters Pattern with Generics Oren’s technique for implementing the Pipes and Filters in the .NET Framework is based on a Generic interface and a Generic class. The Generic interface simulates the filter and the Generic class simulates the pipeline. The IOperation interface has a single method called Execute that is the implementation of the filter logic. Each filter should implement this interface. using System.Collections.Generic;namespace KwicPipesFilters{ public interface IOperation { IEnumerable Execute(IEnumerable input); } The use of a generic IEnumerable is a good choice because it leaves a lot of space for the developers to plug in any type that they want and use various types for their filters. The Pipeline class has an Execute and a Register method. Using the Register method, you add different filters to the pipeline and using the Execute method, you start processing the item in all the registered filters. using System.Collections.Generic;namespace KwicPipesFilters{ public class Pipeline { private readonly List> operations = new List>(); public Pipeline Register(IOperation operation) { operations.Add(operation); return this; } public void Execute() { IEnumerable current = new List(); foreach (IOperation operation in operations) { current = operation.Execute(current); } IEnumerator enumerator = current.GetEnumerator(); while (enumerator.MoveNext()); } } The implementation of the Pipeline class is straightforward: it keeps a list of filters and provides a Register function that lets you add new filters to your pipeline, and then use the Execute method to execute all the filters in the list to process an input. Reader The Reader filter reads the input text from a file and returns an IEnumerable list of lines. Of course, for the first filter in the pipe we don’t care about the input as the input is read inside the filter itself. using System;using System.Collections.Generic;using System.IO;namespace KwicPipesFilters{ public class Reader : IOperation { public IEnumerable Execute(IEnumerable input) { Console.Title = "Pipes and Filters Pattern in .NET"; Console.WriteLine("Enter the path of the file:"); return File.ReadLines(Console.ReadLine()); } } Shifter The Shifter filter is where the main logic of the KWIC application is implemented. It shifts the words in each line to find all the possible permutations suitable for the index. using System.Collections.Generic;namespace KwicPipesFilters{ public class Shifter : IOperation { public IEnumerable Execute(IEnumerable input) { List shifts = new List(); foreach (string line in input) { string[] words = line.Split(new char[] { ' ' }); for (int i = 0; i <= words.Length - 1; i++) { shifts.Add(string.Join(" ", words)); string firstWord = words[0]; for (int j = 1; j <= words.Length - 1; j++) { words.SetValue(words[j], j - 1); } words.SetValue(firstWord, words.Length - 1); } } return shifts; } } Here we have a basic implementation of the Shifter filter where we split the line into separate words based on the space between them, then shift all the words to find various permutations. Sorter Before returning the final results in the Writer filter, we need to sort the index alphabetically. This is done in the Sorter filter. using System.Collections.Generic;using System.Linq;namespace KwicPipesFilters{ public class Sorter : IOperation { public IEnumerable Execute(IEnumerable input) { LineComparer lineComparer = new LineComparer(); input.ToList().Sort(lineComparer); return input; } } Here I used a LineComparer class to implement the ICcomparer interface for the string type. using System.Collections.Generic;namespace KwicPipesFilters{ public class LineComparer : IComparer { public int Compare(string x, string y) { return string.Compare(x, y); } } Writer Obviously, the last filter should write the index to the output for the user and that’s the purpose of the Writer filter. using System;using System.Collections.Generic;namespace KwicPipesFilters{ public class Writer : IOperation { public IEnumerable Execute(IEnumerable input) { foreach (string line in input) { Console.WriteLine(); Console.WriteLine(line); } Console.ReadLine(); yield break; } } As you see, this filter uses a yield break to avoid returning any result. Pipeline Having all the filter implemented, I also need to implement the pipeline itself in order to register the filters and make the whole thing work. I do this in my KwicPipeline class with a simple code that it has. namespace KwicPipesFilters{ public class KwicPipeline : Pipeline { public KwicPipeline() { Register(new Reader()); Register(new Shifter()); Register(new Sorter()); Register(new Writer()); } } I inherit from the Pipeline class and register my filters in the public constructor. Putting It Together There is only one step remained and that is putting all these things together to start the pipeline. All I need to do is to create an instance of the KwicPipeline class, call its Execute method, and leave the rest to my pipes and filters. namespace KwicPipesFilters{ class Program { static void Main(string[] args) { KwicPipeline pipeline = new KwicPipeline(); pipeline.Execute(); } } Conclusion In this post I implemented the Pipes and Filters pattern in the .NET Framework using a simple and generalized technique that relies on Generics to implement the KWIC application. In my opinion this is one of the best ways to implement this pattern in the .NET Framework. I have uploaded the sample source code package here. Note that the solution is created using Visual Studio 2010 RC1. There are other techniques to implement this pattern in .NET and one specific technique that I have in mind is using the Windows Workflow Foundation. I may work more on this idea and write about it later.
March 25, 2010
by Keyvan Nayyeri
· 17,294 Views
article thumbnail
Four Methods to Automate Development Environment Setup
There are at least four methods that can be used in different combinations to make the process of setting up a complete development environment a lot less painful.
February 16, 2010
by Mitch Pronschinske
· 31,719 Views
article thumbnail
Promiscuous Integration vs. Continuous Integration
The emergence of version control systems makes both promiscuous and continuous integration merging techniques more attractive. Which is better?
February 10, 2010
by Martin Fowler
· 50,081 Views · 2 Likes
article thumbnail
Maven Repository Manager: Nexus Vs. Artifactory
My goal is to compare Sonatype Nexus and JFrog Artifactory,the two leading open source Maven repository managers.
December 14, 2009
by Ori Dar
· 136,066 Views · 4 Likes
article thumbnail
An Introduction to Feature-Driven Development – Part 2
This is the second part of a two-part article introducing Jeff De Luca’s Feature Driven Development (FDD) process. In particular, we are looking at how FDD differs from Scrum and eXtreme Programming-inspired approaches when it comes to working with larger teams and projects. In the first part we briefly introduced the ‘just enough’ upfront activities that FDD uses to support the additional communication that inevitably is needed in a larger project/team. In the second part of the article we cover how FDD leverages the results of those upfront activities within the highly iterative, self-managing, organized-chaos that is the delivery engine room of an FDD project. The Engine Room: Delivering Frequent, Tangible Working Results Once there is an initial overall model (FDD Process #1), an initial overall features list (FDD Process #2), and an initial overall plan (FDD Process #3) in place, an FDD project is ready to start delivering the required software feature by feature. Peter Coad, the Chief Architect on the original FDD project used the phrase ‘Deliver frequent, tangible, working results’ as a mantra to impress upon people the idea of delivering real, completed, client-valued function as often as possible. Scrum and eXtreme Programming do this using fixed length iterations of a calendar month or 2-4 weeks. FDD is different. Each Chief Programmer (lead developer) runs a series of iterations, each of which is normally a matter of a few days, and never longer than two weeks. At the start of each of these iterations, each Chief Programmer selects the next few features that make sense to implement from the backlog of feature sets (activities) that were assigned to him or her in FDD Process #2. The Chief Programmer leads the development of these features through FDD processes #4 and #5, Design by Feature (DBF) and Build By Feature (BBF). Note that iterations through the DBF/BBF processes are not fixed length, and Chief Programmers do not synchronize the start and end of their iterations with each other. In addition, the DBF/BBF processes are always executed as a pair (FDD describes them as two separate processes rather than one combined process for psychological reasons). FDD Process #4: Design By Feature After selecting the features for the iteration, a Chief Programmer needs to form their feature team. Yes, feature teams are formed and disbanded for each iteration through the DBF/BBF process pair. Using the knowledge gained from the modeling process (FDD Process #1), the Chief Programmer identifies the domain classes that are likely to be involved in this iteration, and forms his or her feature team from the owners of those classes. In practice, this means: a feature team is small, typically 3 to 5 people, because features are small. By definition, a feature team comprises of all the class owners who need to modify their classes in the development of the features during that iteration. There is no need to wait for members of other teams to change code. Therefore, there are all the benefits of code ownership and a sense of collective ownership too. Class owners may find themselves a member of multiple feature teams at the same time. This does not happen as frequently as might be supposed because iterations are so short – days not weeks. When it does, it is not a big problem in practice. Chief Programmers work together to resolve any problematic conflicts and, with care, most developers can manage the demands of occasionally belonging to more than one feature team for a short time. Once formed, the Chief Programmer facilitates the collaborative analysis and design of the features for that iteration. Depending on the complexity, this may involve the team walking through the requirements in detail with a domain expert, and studying any existing relevant documents. It also involves agreeing on the interactions and other details that need to be added to the model to support the new features. The final step in the DBF part of the iteration is to review the design. For simple features, this may be a brief sanity check of the design held within the feature team. For more significant features, the Chief Programmer will typically involve other Chief Programmers or class owners so that they are aware and can comment on the impact of the proposed design. For small team projects, the object models are frequently small enough for individual or pairs of developers to create good designs while writing tests for a particular feature or user story. For larger projects, this is not necessarily the case and designs created purely by considering the tests a feature or user story must pass are more likely to be brittle and require significant refactoring. The DBF process in FDD ensures that the overall model also guides the design, helping to maintain its ‘conceptual integrity’ [Brooks]. FDD Process #5: Build By Feature The Build by Feature (BBF) part of the iteration involves the team members coding up the features, testing them at both unit level and feature level, and holding a code inspection before promoting the completed features into the project's regular build process. Testing FDD expects developers to unit test their code. It expects feature teams to test their features. FDD is not overly concerned with how this is achieved. Projects and feature teams are free to adopt the testing tools, frameworks, and level of formality and completeness that are most appropriate. FDD does not mind if tests are written before or after code. What FDD mandates, is that the feature team deliver code that has been appropriately tested and inspected. Only once the new features have passed testing and inspection is the source code allowed into the build process. Code Inspections Most people want to know why FDD mandates code inspections, especially those that have endured sitting through hours of boring, unproductive, ego-polishing/demolishing, point-scoring sessions that formed so-called code reviews, inspections or walkthroughs. The reason FDD mandates code inspections is that research has shown time and again that when done well, inspections find more defects and different kinds of defects than testing [McConnell]. Not only that but by examining the code of the more experienced, knowledgeable developers on the team and having them explain the idioms they use, less experienced developers learn better coding techniques. In addition, knowing that their code will be inspected and not be allowed in the build unless it conforms to the agreed standards encourages developers to pay more attention to conforming to those standards. One of the benefits of working in feature teams is that the whole feature team is on the hot seat during an inspection, not just one individual. This removes much of the intensity and anxiety inherent in inspecting one individuals work. The Chief Programmer decides on the level of formality of each inspection depending on the complexity and impact of the features developed in that iteration. Where the code has little or no impact outside the feature team, an inspection will usually only involve the feature team inspecting each other’s work. Where there is significant impact the Chief Programmer pulls in other Chief Programmers and developers to both verify the code and communicate the impact of the new features. eXtreme Programming acknowledges inspections as a ‘best practice' but promotes pair programming as the logical conclusion of applying this practice. Pair programming is obviously better than individual developers delivering code without any form of inspection. However, while FDD neither mandates nor forbids pair programming, a more-traditional inspection is: fresh eyes looking at the code, catching bad assumptions made by the coder/s a Chief Programmer present to ensure the techniques passed on are good. After all, developers can just as easily teach each other bad habits as well as good habits. a change of pace for developers, a chance to step away from the keyboard and mouse for a short while. With the wide availability of automated source code formatting and static analysis tools, code inspections can now be shorter, concentrating on the logic and coding idioms involved and not getting bogged down in nit-picking such as alignment of braces, etc. The Build FDD assumes some sort of regular build process. Some teams build weekly, others daily and others continuously. FDD avoids mandating any particular build regime. This enables the project team to apply the most applicable. If a continuous integration environment makes sense, then the team is free to employ the best there is. Progress Reports Agile projects like highly visible progress information. FDD projects are no exception. In fact, because larger projects frequently have higher profiles within an organization, presenting meaningful, accurate, timely project information appropriately at the different levels of leadership/management is even more important. Conventionally, FDD projects track the development of each feature through its DBF/BBF iteration against six milestones: domain walkthrough, design, design inspection, coding, testing and inspection, and promoted to build. For each feature, Chief Programmers record the actual date a milestone is reached. Tracking each feature through these six milestones enables the project to keep an eye on how much work is 'in progress'. Too many features at a particular milestone indicate a process problem. Those promoting Kanban and other Limited Work In Progress methods have formalized this idea to strictly define what is meant by 'too many' for each of their development iteration milestones/statuses. They then refuse to move an item to a new milestone/status if the limit on the number of items at that status has been reached. This forces a team to keep items moving forward through the process [Kanban]. FDD is not so formal, leaving the Chief Programmers and Development Manager to keep an eye informally on the amount of work in progress. The Big Wallchart, Burn-Down/Up Charts, Etc For general visibility of progress within a project, the team typically lists all the features in the project complete with their owning Chief Programmer, feature team members, and the dates of each milestone achieved on a suitable wall. In addition, features can be colored to show if they are started, in-progress, completed or blocked. This allows people to stand back from the wall and get a good visual feel for the overall status of the project. They can then walk up to the wall to zoom in on particular areas and activities in more detail. Recording the date each milestone is achieved enables a team to produce burn-down or burn-up charts analogous to those produced in Scrum and XP. Chief Programmers and Project Managers can determine from these if the underlying rate of feature completion is increasing, decreasing, or stable, etc. One of the best ways to achieve this is to have the Chief Programmers regularly (typically once a week) communicate progress to either the project manager or someone dedicated to the task. That person then produces whatever roll-up and burn-down charts desired. Having an administrative person, the equivalent of the Tracker role in eXtreme Programming, perform these report formatting duties frees the Chief Programmers to spend more time on making progress rather than formatting reports about it. Parking Lot Charts For reporting to senior management, the level of individual features is often too granular. Here, FDD projects typically use a graphical report format that known as the Parking Lot chart. In a Parking Lot chart, each group of ‘parking lots’ represents one of the subject areas from the features list. Each parking lot represents one of the activities within that subject area, and displays the name of that set of features, the number of features within it, and the percentage of those features that have been completed (typically both in text and using a progress bar). The parking lots are also colored to indicate whether the features in that activity have been started, completed, or have significant blockages. The FDD parking lot format has become so popular that Mike Cohn included it in his book, Agile Planning and Estimating [Cohn]. (click for larger image) Figure 1: Example Parking Lot Chart Conclusion Feature-Driven Development combines the key advantages of other popular agile approaches with model-centric techniques and other best practices that scale to much larger teams and projects. It defines three upfront activities that provide a conceptual and management framework within which a larger-than-usual agile team can add functionality to the software, feature by feature. It is also just as applicable for smaller teams tackling non-trivial problem domains where it is worth spending just a little time to sketch a map of the journey before dashing off down the agile coding highway. Even if you and your team decide not to adopt FDD as a whole, understanding why FDD is the way it is, can provide insight into scaling traditional agile approaches beyond small, largely independent teams. Finally, I would like to say thank you to Serguei Khramtchenko and Mark Lesk at Nebulon for their corrections and suggestions incorporated in this article. References [Brooks] Frederick P. Brooks, Jr., The Mythical Man-Month, Addison Wesley [Cohn] Cohn, Agile Planning and Estimating, Prentice-Hall PTR [FDD] FDD Community Site, www.featuredrivendevelopment.com/ [Kanban] The home of Kanban software development, www.limitedwipsociety.org/ [McConnell] McConnell, Code Complete, Microsoft [Nebulon] The Latest FDD Processes available from www.nebulon.com/articles/fdd/latestprocesses.html [Palmer-1] Palmer, Felsing, A Practical Guide to Feature-Driven Development, Prentice Hall PTR
December 4, 2009
by Stephen Palmer
· 25,500 Views · 1 Like
article thumbnail
TFS Build: _PublishedWebsites for exe and dll Projects
We’re using TFS on my current project. Yes, yes, I know. It’s generally good practice to collect all the code under your team’s control in a single uber-solution as described in this Patterns and Practices PDF, Team Development with TFS Guide. If you then configure the TFS build server to build this solution, it’s default behaviour is to place the build output into a single folder, ‘Release’. Any web application projects in your solution will also be output to a folder called _PublishedWebsites\. This is very nice because it means that you can simply robocopy deploy the web application. Unfortunately there’s no similar default behaviour for other project types such as WinForms, console or library. It would be very nice if we could have a _PublishedApplications\ sub folder with the output of any selected project(s). Fortunately it’s not that hard to do. The way _PublishedWebsites works is pretty simple. If you look at the project file of your web application you’ll notice an import near the bottom: On my machine the MSBuildExtensionsPath property evaluates to C:\Program Files\MSBuild, if we open the Microsoft.WebApplication.targets file we can see that it’s a pretty simple MSBuild file that recognises when the build is not a desktop build, i.e. it’s a TFS build, and copies the output to: $(OutDir)_PublishedWebsites\$(MSBuildProjectName) I simply copied the Micrsoft.WebApplication.targets file, put it under source control with a relative path from my project files and changed _PublishedWebsites to _PublishedApplications and renamed the file CI.exe.targets. For each project that I want to output to _PublishedApplications, I simply added this import at the bottom of the project file: You can edit CI.exe.targets (or whatever you want to call it) to do your bidding. In my case, the only change so far is to add a couple of lines to copy the App.config file: There’s a lot of stuff in Microsoft.WebApplication.targets that’s only relevant to web applications and can be stripped out for other project types, but I’ll leave that as an exercise for the reader. There was also a discussion on StackOverflow, with some nice alternative suggestions of how you might want to do this. It’s worth checking out.
June 12, 2009
by Mike Hadlow
· 11,252 Views
article thumbnail
Hibernate Performance Tuning
Hibernate is a powerful, high performance object/relational persistence and query service. Hibernate lets you develop persistent classes following object-oriented idiom - including association, inheritance, polymorphism, composition, and collections. Hibernate allows you to express queries in its own portable SQL extension (HQL), as well as in native SQL, or with an object-oriented Criteria and Example API. Quintessential to using any ORM framework like hibernate is to know how to leverage the various performance tuning methods supported by the framework. In this volume Wings Jiang discusses three performance tuning strategies for hibernate: SQL Optimization Session Management Data Caching SQL Optimization When using Hibernate in your application, you already have been coding HQL (Hibernate Query Language) somewhere. For example, “from User user where user.name = ‘John’”. If issuing your SQL statement like this, Hibernate cannot use the SQL cache implemented by database because name of the user, in most scenarios, is extremely distinct. On the contrary, while using placeholder to achieve this, like “from User user where user.name =?” will be cached by the Database to fulfill the performance improvement. You can also set some Hibernate properties to improve performance, such as setting the number of records retrieved while fetching records via configuring property hibernate.jdbc.fetch_size, setting the batch size when committing the batch processing via configuring property hibernate.jdbc.batch_size and switching off the SQL output via setting property hibernate.show_sql to false in product environments. In addition, the performance tuning of your target Database is also significant, like SQL clauses tuning, reasonable indexes, delicate table structures, data partitions etc. Session Management Undoubtedly, Session is the pith of Hibernate. It manages the Database related attributes, such as JDBC connections, data entities’ states. Managing the Session efficiently is the key to getting high performance in enterprise applications. One of the many commonly used and equally elegant approaches to session management in hibernate is to use ThreadLocal. Threadlocal will create a local copy of session for every thread. Thus synchronization problems are averted, when objects are put in the Threadlocal, . To understand how ThreadLocal variables are used in Java, refer to Sun Java Documentation at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadLocal.html Data Caching Before accomplishing any data caching, it is essential to set the property hibernate.cache.user_query_cache = true. There are three kinds of commonly used Caching Strategies in Hibernate: Using cache based on Session level (aka Transaction layer level cache). This is also called first-level cache. Using cache based on SessionFactory level (Application layer level cache). This is also called second-level cache. Using cluster cache which is employed in distributed application (in different JVMs). In fact, some techniques, like loading data by id, lazy initialization which betokens loading appropriate data in proper time rather than obtaining a titanic number of useless records, which are fairly useless in the subsequent operations are consummated via data caching. First Level Cache (aka Transaction layer level cache) Fetching an object from database always has a cost associated with it. This can be offset by storing the entities in hibernate session. Next time the entities are required, they are fetched from the session, rather than fetching from the database. To clear an object from the session use: session.evict(object). To clear all the objects from the session use session.clear(). Second Level Cache (aka Application layer level cache) In this approach, if an object is not found in session, it is searched for in the session factory before querying the database for the object. If an object is indeed fetched from database, the selected data should be put in session cache. This would improve the performance when the object is required next time. To remove an entity from session factory use the various overloaded implementations of evict() method of SessionFactory. In fact, Hibernate lets you tailor your own caching implementation by specifying the name of a class that implements org.hibernate.cache.CacheProvider using the property hibernate.cache.provider_class. But it is recommended to employ a few built-in integrations with open source cache providers (listed below). Cache Type Cluster Safe Query Cache Supported Hashtable Memory NO YES EHCache Memory, Disk NO YES OSCache Memory, Disk NO YES SwarmCache Clustered YES (clustered invalidation) NO JBoss TreeCache Clustered YES (replication) YES Terracota Clustered YES YES In order to use second level caching, developers have to append some configurations in hibernate.cfg.xml (for example, using EHCache here). net.sf.ehcache.hibernate.Provider In addition, developers also need to create a cache specific configuration file (Example: ehcache.xml for EHCache). (1) diskStore : Sets the path to the directory where cache .data files are created. The following properties are translated: a.user.home - User's home directory b.user.dir - User's current working directory c.java.io.tmpdir (Default temp file path) maxElementsInMemory : Sets the maximum number of objects that will be created in memory. eternal : Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. timeToIdleSeconds : Sets the time to idle for an element before it expires. Is only used if the element is not eternal. Idle time is now - last accessed time. timeToLiveSeconds : Sets the time to live for an element before it expires. Is only used if the element is not eternal. TTL is now - creation time overflowToDisk : Sets whether elements can overflow to disk when the in-memory cache has reached the maxInMemory limit. Finally the cache concurrency strategy has to be specified in mapping files. For example, the following code fragment shows how to configure your cache strategy. … … Cache Concurrency Strategies There are four kinds of built-in cache concurrency strategies provided by Hibernate. Chosing a right concurrency strategy for your hibernate implementation is the key to cache performance optimization. Besides to ensure data consistency and transaction integrity it is indispensable to master these strategies. read-only If your application needs to read but never modify instances of a persistent class, a read-only cache may be used. This is the simplest and best performing strategy. It's even perfectly safe for use in a cluster. nonstrict-read-write If the application only occasionally needs to update data (For example, if it is extremely unlikely that two transactions would try to update the same item simultaneously) and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate. read-write If the application needs to update data, a read-write cache might be appropriate. This cache strategy should never be used if serializable transaction isolation level is required. transactional If the application seldom needs to update data and at the same time, application also needs to avoid “dirty read” and “repeatable read”, this kind of concurrency strategy can be employed. The transactional cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. The following table lists cache concurrency strategy supported by various cache providers. Cache Read-only Nonstrict-read-write Read-write Transactional Hashtable YES YES YES N/A EHCache YES YES YES N/A OSCache YES YES YES N/A SwarmCache YES YES N/A N/A JBoss TreeCache YES N/A N/A YES Cluster Cache (in different JVMs) Hibernate also supports cluster caching in disparate JVMs. At present, both SwarmCache and JBoss TreeCache support cluster caching across multiple JVMs. In some situations, especially at the level of enterprise, certain application has to support the concurrency accessing of thousands of users, at that time, cluster cache can help you because the cluster can provide failover and load balancing which improve the performance of application. Points to Note When employing one of the four cache strategies above, pay close attention to the following situation: Data cached almost immutable If data you want to cache is almost constant, you can use data caching which can improve the performance of the application. On the contrary, if the caching data are quiet volatile, Hibernate have to maintain and update the caching over time which extremely leads to performance hit. Data sizes in reasonable range If the size of data you is caching is massive, Hibernate will occupy the most memories of system, which causes the long waiting time of the whole application. Low frequency of data updating If data you are caching needs to be modified frequently, Hibernate have to take an array of time to update and modify the data in caching, which impacts the performance of the application as well. High frequency of data querying If data you are caching is steady, which means that most of the operations are querying, searching, no updating and modifying, making the most use of caching will be affording huge performance improvement. None crucial data Because of existing some incongruities when keeping the data in caching, so if the data you are caching is fairly crucial, do not use caching. By contrast, if the data in caching is insignificant, just use it without any vacillation. Summary Actually, after employing SQL Optimization, Session Management, Data Caching, we will obtain great battalions of performance gains, which make applications achieve acceptable waiting time for the final customers. External Links for Further Study http://www.hibernate.org/hib_docs/reference/en/html/performance.html http://blogs.jboss.com/blog/acoliver/2006/01/23/Hibernate_EJB3_Tuning.txt About Author I am Wings Jiang from BCM China. I have mainly focused on J2EE technologies in recent years and worked in several projects involving Struts/Tapestry, Spring, Hibernate, WebLogic, Websphere, Oracle, DB2 etc. I have experience in design and code of several Java applications. Hibernate performance is one of the areas I pay close heed to in my current working.
June 10, 2009
by Ming Jiang
· 141,805 Views · 4 Likes
article thumbnail
Integrate OpenOffice with Java without Installing OpenOffice
Until a few days ago, I've always needed to work with the rather cumbersome Office Bean and UNO Runtime when integrating OpenOffice into a Java application. I also had to configure a whole bunch of things to force OpenOffice to play nicely with the Java integration. Two days ago, however, I found out about ODF Toolkit. It seems to be a relatively new project, independent since last year some time, though I could be wrong. What's especially interesting is the ODFDOM: ''ODFDOM is an OpenDocument (ODF) framework. It's purpose is to provide an easy common way to create, access and manipulate ODF files, without requiring detailed knowledge of the ODF specification. It is designed to provide the ODF developer community an easy lightwork programming API, portable to any object-oriented language.'' Here's a snippet of it in action: public static void main(String[] args) { try { OdfDocument odfDoc = OdfDocument.loadDocument(new File("/home/geertjan/test.ods")); OdfFileDom odfContent = odfDoc.getContentDom(); XPath xpath = odfDoc.getXPath(); DTMNodeList nodeList = (DTMNodeList) xpath.evaluate("//table:table-row/table:table-cell[1]", odfContent, XPathConstants.NODESET); for (int i = 0; i < nodeList.getLength(); i++) { Node cell = nodeList.item(i); if (!cell.getTextContent().isEmpty()) { System.out.println(cell.getTextContent()); } } } catch (Exception ex) { //Handle... } } Let's assume that the 'test.ods' file above has this content: From the above, the code listing would print the following: Cuthbert Algernon Wilbert And, as a second example, here's me reading the first paragraph of an OpenOffice Text document: public static void main(String[] args) { try { OdfDocument odfDoc = OdfDocument.loadDocument(new File("/home/geertjan/chapter2.odt")); OdfFileDom odfContent = odfDoc.getContentDom(); XPath xpath = odfDoc.getXPath(); OdfParagraphElement para = (OdfParagraphElement) xpath.evaluate("//text:p[1]", odfContent, XPathConstants.NODE); System.out.println(para.getFirstChild().getNodeValue()); } catch (Exception ex) { //Handle... } } On my classpath I have "odfdom.jar" and "xerces-2.8.0.jar". I don't necessarily have OpenOffice installed, which means I can very easily process a whole bunch of spreadsheets (or other OpenOffice output) without (a) installing OpenOffice and (b) faster than I would otherwise do, since OpenOffice doesn't need to be started up, via the Office Bean or otherwise. In fact, Aljoscha Rittner from Sepix, who told me about this project and who is using it in his commercial applications, reports that his processing has sped up to a fraction of the original, also because he doesn't need to handle the situation where OpenOffice would crash randomly in the middle of long running processes, such as during the night when there's no human interaction for restarting it.
February 7, 2009
by Geertjan Wielenga
· 50,447 Views
article thumbnail
The Three Pillars of Continuous Integration
Continuous Integration commonly known as CI is a process that consists of continuously compiling, testing, inspecting, and deploying source code. In any typical CI environment, this means running a new build every time code changes within a version control repository. Martin Fowler describes CI as: A software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly. While CI is actually a process, the term Continuous Integration often is associated with three important tools in particular. As shown in the image the three pillars of CI are: 1. A version control repository like Subversion, or CVS. 2. A CI Server such as Hudson, or Cruise Control 3. An automated build process like Ant or Nant So, let’s look at each of these in detail: Version Control Repository: Version control repositories also known as SCM (source code management) play a crucial role in any software development environment. They also play a very important role for a successful CI process. The SCM is a central place for the team to store every needed artifact for the project. It is mandatory for the teams to put everything needed for a successful build into this repository. This includes the build scripts, property files, database scripts, all the libraries required to build the software and so on. The CI Server: For CI to function properly, we also need to have an automated process that monitors a version control repository and runs a build when any changes are detected. There are several CI servers available, both open source and commercial. Most of them are similar in their basic configuration and monitor a particular version control repository and run builds when any changes are detected. Some of the most commonly used open source CI servers are; Cruise Control, Continuum, and Hudson. Hudson is particularly interesting because of its ease of configuration and compelling plug-ins, which makes integration with test and static analysis tools much easier. Automated Build: The process of CI is about building software often, which is accomplished through the use of a build. A sturdy build strategy is by far the most important aspect of a successful CI process. In the absence of a solid build that does more than compile your code, CI withers. With automated builds, teams can reliably perform (in an automated fashion) otherwise manual tasks like compilation, testing, and even more interesting things like software inspection and deployment. Now that we have seen the important tools in our CI process, let’s see how a typical CI scenario looks like for a developer: CI server is configured to poll the version control repository continuously for changes. Developer commits code to the repository. CI server detects this change, and retrieves the latest code from the repository. This causes the CI server to invoke the build script with the given targets and options. If configured, CI Server will send out an e-mail to the specified recipients when a certain important event occurs. The CI server continues to poll for changes. Why is CI Important? This is one of the most frequently asked questions, and here are a few points to note about this powerful technique: Building software often greatly increases the likelihood that you will spot defects early, when they still are relatively manageable. Extends defect visibility. CI ensures that you have production ready software at every change. CI also ensures that you have reduced the risk of integration issues by building software at every change. CI server can also be configured to run continuous inspection which can assist the development team in finding potential bugs, bad programming practice, automatically check coding standards, and also provide valuable feedback on the quality of code being written. Over the past several months, I have assisted several companies in implementing CI. There was a little bit of resistance from the developers in the early stages when we implemented continuous feedback. But, never heard a single negative comment about this approach. If you already have a version control repository and automated builds, you are very close to the CI process. Download one of the open source CI servers, configure and setup a simple project. It should take less than an hour if you have automated build scripts. Start adding additional features like code inspections, generating reports, metrics, documentation and so on. Most important, send continuous feedback to your team. Give this process a try, you sure will be surprised to see how effective it is. And, as always share your thoughts, concerns or questions.
December 15, 2008
by Meera Subbarao
· 23,859 Views
article thumbnail
A Look Inside the JBoss Microcontainer, Part I -- Component Models
Looking at the current state of Java, we can see that POJOs (Plain Old Java Objects) rule the land yet again. Their dominance stretches from enterprise applications to middleware services. At JBoss we were known for our modular JMX-based kernel. The application server was nothing more than a bunch of flexible MBeans and a powerful MicroKernel in the middle. But, as you could feel the change is coming, we still wanted to be ahead of the pack. We could see different POJO based component models popping up all over the place (EJB3, JPA, Spring, Guice, … to name a few), yet nothing was out there that would bind them all, flattening out the differences on a single component model. Hence the Microcontainer project was born. The JBoss Microcontainer project is about many things. The Microcontainer's features range from reflection abstraction, a virtual file system, a simple state machine to transparent AOP integration, a new classloading layer, a deployment framework and an OSGi framework implementation. I'll try to address them all over a short series of articles that will be published here on DZone. This article will examine the Microcontainer's component models. Read the other parts in DZone's exclusive JBoss Microcontainer Series: Part 1 -- Component Models Part 2 –- Advanced Dependency Injection and IoC Part 3 -- the Virtual File System Part 4 -- ClassLoading Layer Part 5 - the Virtual Deployment Framework Part 6 - The Scanning Library What is a component model? What do we consider a component model? First of all, what do we consider being a component? One abstract way to express this would be that “components are reusable software programs that you can develop and assemble easily to create sophisticated applications.” To consider a bunch of components as an actual model, we also need to declare what kind of interactions we allow. JMX MBeans are one example of a component model. Their interactions include executing MBean operations, referencing attributes, setting attributes and declaring explicit dependencies between named MBeans. As mentioned, we had advanced JMX handling already with the MicroKernel. And as expected, the Microcontainer brought extensive POJO support. The default behavior and interactions in the Microcontainer are what you also normally get from any other IoC container and are similar to the functionality that MBeans provided: plain method invocations for operations, setters/getters for attributes and explicit dependencies. However, having only this functionality would mean we didn't get much further than just relieving the pain of declaring MBeans, hence it was only logical for us to do something more. I'll leave the discussion of these new IoC features for the next article in the series. There are many existing POJO component models out there, Guice and Spring being amongst the most popular. Effective integration with these frameworks was an important goal for us. Demo environment setup Before we begin, I'd like to first describe the various parts that constitute the demo. All the source code can be found at this location of our Subversion repository: • http://anonsvn.jboss.org/repos/jbossas/projects/demos/microcontainer/branches/DZone_1_0/ The project is fully mavenized, so it should be easy to adjust it to your IDE. I will first go over the sub-projects within the demo and describe their usage. At the end of my article series, I will provide a more detailed look at what certain sub-projects do. Below are the JBoss Microcontainer demos and sub-projects that are relevant for this article: • bootstrap (as the name suggests, it bootstraps the Microcontainer with demo code) • jmx (adds the JMX notion to demo's bootstrap) • models (source code of our components / services) The demo has only one variable you need to set - demos home - but even this one can be optional if you checked-out your project into the \projects\demos directory. Otherwise, you need to set the system property demos.home (e.g. -Ddemos.home=). You should now be able to run JMXMain as a main class. Make sure you include the models sub-project in the classpath, since some of the services require additional classes in the classpath, several more then what the jmx sub-project expects. Once the Microcontainer is booted it starts to scan the ${demos.home}/sandbox directory for any changes. Now all we need to do is provide a deployable unit and drop it in there. Models Let’s now turn our attention to the models sub-project. This is where the previously mentioned deployable unit should come from. You can see if everything is in place by building the models sub-project (mvn package) and dropping it into the sandbox. You should get a bunch of debug and info messages on the console log, showing how the Microcontainer got booted. Any error message indicates some problems. Let’s go over exactly what the models sub-project does, its integration code and try to redeploy it. If we look at the models src/main/resources/META-INF directory, we'll see plenty of -beans.xml resource files and one -service.xml. You’ll notice that each has a meaningful name that matches the source code package from models's src/main/java/org/jboss/demos/models directory. Let's dissect them one by one, starting with the ones that have no dependencies. org.jboss.demos.models.plain.PojoFactory This is a simple Micrcocontainer beans descriptor file. Anyone who crossed paths with some other IoC’s configuration file should be familiar with it. And, as I already mentioned, I'll follow up on more advanced usage in the next article. The next file shows what we have done to support Spring integration: Note that this file's namespace is different from the previous Microcontainer bean’s plain-beans.xml file. The urn:jboss:spring-beans:2.0 namespace points to our version of the Spring schema port, meaning you can describe your beans Spring style, but it's the Microcontainer that's going deploy then, not Spring's bean factory notion. public class Pojo extends AbstractPojo implements BeanNameAware { private String beanName; public void setBeanName(String name) { beanName = name; } public String getBeanName() { return beanName; } public void start() { if ("SpringPojo".equals(getBeanName()) == false) throw new IllegalArgumentException("Name doesn't match: " + getBeanName()); } } Although the SpringPojo bean has a dependency on Spring lib via implementing BeanNameAware interface, this dependency is only there to expose and mock some of the Spring's callback behavior (see SpringBeanAnnotationPlugin for more details). Since we introduced Spring integration, let's have a look at Guice integration. As Guice users know, Guice is all about type matching. Configuration of Guice beans is done via Modules which means that in order to generate beans, one must implement a Module. Two important parts to watch from this file are PojoModule and GuiceKernelRegistryEntryPlugin. The first one is where we configure our beans: public class PojoModule extends AbstractModule { private Controller controller; @Constructor public PojoModule(@Inject(bean = KernelConstants.KERNEL_CONTROLLER_NAME) Controller controller) { this.controller = controller; } protected void configure() { bind(Controller.class).toInstance(controller); bind(IPojo.class).to(Pojo.class).in(Scopes.SINGLETON); bind(IPojo.class).annotatedWith(FromMC.class).toProvider(GuiceIntegration.fromMicrocontainer(IPojo.class, "PlainPojo")); } } The second class provides integration with the Microcontainer: public class GuiceKernelRegistryEntryPlugin implements KernelRegistryPlugin { private Injector injector; public GuiceKernelRegistryEntryPlugin(Module... modules) { injector = Guice.createInjector(modules); } public void destroy() { injector = null; } public KernelRegistryEntry getEntry(Object name) { KernelRegistryEntry entry = null; try { if (name instanceof Class) { Class clazz = (Class)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(clazz)); } else if (name instanceof Key) { Key key = (Key)name; entry = new AbstractKernelRegistryEntry(name, injector.getInstance(key)); } } catch (Exception ignored) { } return entry; } } Notice how we created an Injector from the Modules and then did a lookup on it for matching beans. In mbeans-service.xml we declare our legacy usage of MBeans: What’s interesting to note here is how we injected a POJO into an MBean. The preceding demonstrated our first interactions between different component models. In order to allow for MBean deployment via the Microcontainer, we had to write entirely new component model handling code. See the system-jmx-beans.xml for more details. The code from this file lives in the JBossAS source code: system-jmx sub-project. One note here, this is currently only possible with JBoss's JMX implementation, since the system-jmx code uses some implementation details. Now what if we wanted to expose our existing POJOs as MBeans, registering them into an Mbean server? @org.jboss.aop.microcontainer.aspects.jmx.JMX(exposedInterface=org.jboss.demos.models.mbeans.PojoMBean.class, registerDirectly=true) As you can see from looking at any of the beans in this file, in order to expose your POJOs as MBeans, it’s simply a matter of annotating them with an @JMX annotation. You can either expose the bean directly or its property: Here we see how you can use any of the injection lookup types by either looking up a plain POJO or getting a handle to an MBean from the MBean server. One of the injection options is to use type injection, which is also sometimes called autowiring: The FromGuice bean injects the Guice bean via type matching, where PlainPojo is injected with a common name injection. We then test if Guice binding works as expected: public class FromGuice { private IPojo plainPojo; private org.jboss.demos.models.guice.Pojo guicePojo; public FromGuice(IPojo plainPojo) { this.plainPojo = plainPojo; } public void setGuicePojo(org.jboss.demos.models.guice.Pojo guicePojo) { this.guicePojo = guicePojo; } public void start() { f (plainPojo != guicePojo.getMcPojo()) throw new IllegalArgumentException("Pojos are not the same: " + plainPojo + "!=" + guicePojo.getMcPojo()); } } This only leaves us with an alias component model. Even though the alias is quite a trivial feature, in order to implement it as a true dependency, it has to be introduced as a new component model inside the Microcontainer. The implementation details for this is part of the AbstractController source code: springPojo Here we’ve mapped the SpringPojo name to the springPojo alias. The beauty of having aliases as true component models is that it doesn't matter when the real bean gets deployed. This means that the alias will wait in a non-installed state until the real bean triggers it. Conclusion We've seen how we can deploy simple Microcontainer beans, legacy MBeans, Guice POJOs, Spring beans and aliases. And since all of this is controlled by the Microcontainer, we saw how easily we can mix and match the different component models. I can easily say, with the level of abstraction we put in our component model design, the sky is the limit on what we can handle. An example of this is the upcoming OSGi services, but that's another story, another article. Stayed tuned for my next article which will provide a detailed look at the Microcontainer's IoC functionality. About the Author Ales Justin was born in Ljubljana, Slovenia and graduated with a degree in mathematics from the University of Ljubljana. He fell in love with Java seven years ago and has spent most of his time developing information systems, ranging from customer service to energy management. He joined JBoss in 2006 to work full time on the Microcontainer project, currently serving as its lead. He also contributes to JBoss AS and is Seam and Spring integration specialist. He represent JBoss on 'JSR-291 Dynamic Component Support for Java SE' and 'OSGi' expert groups.
October 1, 2008
by Ales Justin
· 57,241 Views
article thumbnail
Ant or Gant?
Yes, this is exactly what I am frequently asked by my clients and many developers. It isn't easy to answer this question. There are several projects using Ant. Should you run away from Ant just because there is a new cool tool out there called Gant? Should you switch to Gant just because you dislike XML? Not at all. Let's take a closer look and see what might make you switch to Gant. When to choose Gant? 1. Complicated Build Files. If your ant build files are becoming too complicated, and hard to manage, it's time to see if using Gant can help. Let me explain what I mean by complicated build files. If you have too much of conditional logic within your build files, say something similar on the lines shown below in Listing 1: Code Listing 1: Or even something like this where you might be supporting deployment to different application servers based on some property in your build.properties as shown in listing 2. Code Listing 2: Things get out of hand when you have conditional logic as shown above in your build scripts. The listings I have are just the skeleton, imagine what happens when we start adding the actual deployment logic for all these application servers. It doesn't matter how you refactor this, it is still going to be very complicated. Trust me, I have written build scripts which were several thousand lines, and refactoring them was not a trivial task. 2. Custom Ant Tasks. I myself am guilty of writing many of these. There are many situations which arise in projects where we create custom ant tasks. It is simple once you know how to write one, and than for every complicated task you need to perform, you involuntarily will start writing custom ant tasks. Anyone writing a custom ant task will: a. Create a new class that extends Ant’s org.apache.tools.ant.Task class. b. For each attribute, write a setter method. c. Write an execute()method that does what you want this task to do. There isn't anything wrong in doing the above, but imagine each time you want to make a small change, you will have to make changes within your Java source code, compile, test, and re-package. 3. Scripting. You can extend Ant further by not writing custom ant tasks, but by using small snippets of code written in an interpreted language like JRuby, BeanShell, or Groovy. These code snippets can be placed within your build files or in separate text files. If you are using Groovy's Ant task, your build file might look something like this: Code Listing 3: import some.package import another.package def fullpath = "${.basedir}/${defaulttargetdir}" def somefile = new SomeFile(projectName:"${pname}", buildLabel:"${label}", buildTime:"${new Date()}") def xml = "${fullpath}/dashboard.xml" new File(path).write(somefile.generateReport()) ant.xslt(in:path, out:"${properties.defaulttargetdir}/some.html", style:"${properties.defaulttargetdir}/lib/report-style.xsl") Imagine having several lines of XML in your build files which have many of these small snippets of scripts. I myself don't like mixing and matching build files with code snippets. If you have a team where everyone is in the same page, everything works fine. What if a team member has no clue about any of the Scripting languages? He/She will have no clue how to make minor changes when things go badly. If you have all the above or even one of the above three cases, you seriously need to consider using Gant. To quote Aristotle: For the things we have to learn before we can do them, we learn by doing them." So, lets see how easy it is to learn Gant and see how things can improve. This part covers the very basics of Gant. The next part, will dive deeper into Gant by using it with a sample project to build an application, and we will also see how to use it with our CI Server. What's Gant? Gant is a build tool that uses both Groovy and Ant. With Gant, you describe your build process using Groovy scripts. Stated simply, Gant allows you to specify the build logic using Groovy instead of XML. The next thing you may ask is " Is Gant a competitor to Ant?". Let me quote from the Gant web site to make thing more clear here : Whilst it might be seen as a competitor to Ant, Gant uses Ant tasks for many of the actions, so Gant is really an alternative way of doing builds using Ant, but using a programming language rather than XML to specify the build rules. Download and Install Gant. In order for Gant to work, you should have Groovy installed. You can download and follow the installation instructions for Groovy here. As I said earlier also, in order to use Gant, you should have knowledge of Groovy as well. If you have never written Groovy code before, there are many interesting books on Groovy like: 1. Groovy in Action 2. Groovy Recipes 3. Groocy Refcardz You can also read the getting started guide on the Groovy web site, which should give you a good starting point. Download the latest version of Gant from here. Gant is currently at version 1.4.0. Unzip it to a folder. If you already have your GROOVY_HOME set, that's all you need to use Gant. Getting Started. Open a console, and type gant. You should see a message as shown below: meera-subbaraos-macbook-9:~ meerasubbarao$ gant Cannot open file build.gant meera-subbaraos-macbook-9:~ meerasubbarao$ You are all set at this point to use Gant in your projects. Help Information: Open a console, and type gant -h. This will provide you with all the necessary help information you need as shown below: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant -h usage: gant [option]* [target]* -c,--usecache Whether to cache the generated class and perform modified checks on the file before re-compilation. -n,--dry-run Do not actually action any tasks. -C,--cachedir The directory where to cache generated classes to. -D = Define to have value . Creates a variable named for use in the scripts and a property named for the Ant tasks. -L,--lib Add a directory to search for jars and classes. -P,--classpath Specify a path to search for jars and classes. -T,--targets Print out a list of the possible targets. -V,--version Print the version number and exit. -d,--debug Print debug levels of information. -f,--file Use the named build file instead of the default, build.gant. -h,--help Print out this message. -l,--gantlib A directory that contains classes to be used as extra Gant modules, -p,--projecthelp Print out a list of the possible targets. -q,--quiet Do not print out much when executing. -s,--silent Print out nothing when executing. -v,--verbose Print lots of extra information. Create a new file called build.gant at the root of your project. Did a similarity between Ant and Gant strike you here? Ant build files are usually called build.xml, and they are created as a common practice within the root of your project folder as well. If you have written or even modified Ant build files, you will know that it contains one project element, which in turn contains a name,the default target and the base directory. Code Listing 4: So for example, sayHello target in Ant would look something like this: Lets create the sayHello target, and also see how to set it as the default target in Gant as well. A Gant target has a name and a description: Code Listing 5: target ( target-name : target-description ) { groovy code sequence } The above sayHello target in Gant would translate as shown below: target(sayHello:"Saying hello"){ Ant.echo(message:"Hello Javalobby") } Now, open a command window and type gant at the root of the project where the build.gant file exists. You should be able to see a output like: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant Target default does not exist. Gant is complaining that we haven't set a Default target. Lets see how to do the same: Default target: Within Ant, you define the default target from within the project element as seen in Listing 4. The default target is the target called if no target is specified from the command line. There however is no project tag within Gant. There are two ways of specifying the default target as shown below: 1. You simply create a target whose name is default. target ( 'default' , 'The default target.' ) { aTarget ( ) 2. or even simply: setDefaultTarget ( aTarget ) In order to get our sayHello target working, we need to add one of the above scripts to our build.gant file. Code Listing 6: setDefaultTarget(sayHello) or target ("default": "The default target." ) { sayHello ( ) } Complete listing of build.gant: target(sayHello:"Saying hello"){ Ant.echo(message:"Hello Javalobby") } /* target ("default": "The default target." ) { sayHello ( ) } */ setDefaultTarget(sayHello) And you should be able to see: meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant [echo] Hello Javalobby meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ That was easy! If you have build files and it is becoming unmanageable by your team, there is a tool out there which can convert your Ant scripts to Gant scripts as well. I haven't used it, but you can try it here. In this part of the series, we learned when to move over from Ant to Gant, downloaded and installed Gant, and finally wrote a simple gant build file. In the next part of this series, we will see Gant in Action within a simple Java project. And as always, keep us posted here if you are encountering any problems getting started with Gant. Stay tuned.
September 23, 2008
by Meera Subbarao
· 52,169 Views
article thumbnail
Javadoc or Doxygen?
In the last two articles, "Reverse-engineer Source Code into UML Diagrams" and "Visual Documentation of Ant Dependencies in 3 Simple Steps" we saw how easy and valuable it was to automate technical documentation. By using open source tools, we were easily able to provide good technical documentation within a few minutes, and at no cost at all. We were also able to keep this up-to date by adding additional tasks to our Ant build files, and run them from our CI Server(Hudson in our case) on commit and nightly builds, and also publish the results. In this article, I will be showing you how to use yet another tool called Doxygen for generating technical documentation based on your source code. We all have used Javadoc and have been using it for a long time, right? So, you may ask what's the need to have another tool which produces the same HTML documentation? Doxygen has a slight edge over Javadoc and here are a few reasons why you should consider using the same: With Javadoc you have to remember all the HTML tags, you need to embed within your code comments. However, with Doxygen code comments are much more concise and polished, without the need for any HTML. Doxygen can also generate a variety of diagrams, we will take a look at some of them later. Doxygen also provides a structured view on the source code. As I mentioned in 2 above in the form of various diagrams, cross-referenced and syntax highlighted code. You get all the above benefits even if the code does not have any comments at all. Last but not the least, Doxygen is a documentation system not for just Java but also for various other languages like C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#. So, without wasting further time, lets see what we need to get started with Doxygen. Step 1. Download, Install Doxygen. Download the binary distribution for Doxygen for the operating system you are using. I downloaded the binary distribution for Mac OS X called Doxygen-1.5.6.dmg. Installation is very simple, just drag the doxygen icon from this folder to the Applications folder, or wherever you want to keep it; as shown. I dropped it within my Applications folder. Just be sure to remember where you dragged it. To uninstall, just delete the file. It is completely self-contained. Step 2: Configure Doxygen. To generate documentation using Doxygen, you will need a configuration file called the Doxyfile. You can generate this file in two ways; either by using the Doxygen wizard or by using the command line option. Lets see how to use both these options to generate the configuration file: a. Command line. Open a command window and type the following as shown below: You should be able to locate the configuration file created within your default user folder. The file looks like this: # Doxyfile 1.5.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = b. Wizard Option. Launch the Doxygen application, and you should be able to create the configuration file using the wizard approach as shown below. The user interface is quite intuitive so I am going to skip explaining this in detail. The wizard approach was the one I used to get the initial settings for the configuration file. which you can always modify later. A few options in my Doxygen configuration file are as follows: # Doxyfile 1.5.6 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = PetStore PROJECT_NUMBER = 1.0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html GENERATE_TREEVIEW = YES Step 3. Doxygen and Ant. In order to use Doxygen, we need an Ant task. There is already an Ant task written for Doxygen which you can download from here. As always, since using Mac, when I downloaded the binaries and tried to use them, I got the ever famous error message : java.lang.UnsupportedClassVersionError: Bad version number in .class file So, had to do download the source, compile, and jar it up. Copy this library to your projects folder. Next, lets start making changes to our build file. 3.a: Lets define the Doxygen task. 3.b: To generate HTML documentation: 3.c: Lets combine them in target and run: [doxygen] Exec: /Applications/Doxygen.app reports/Doxyfile BUILD FAILED /CodeMetricsProject/build.xml:91: Doxygen not found on the PATH. Total time: 7 seconds 3.d: So, to launch Doxygen not in the path. we make change to the doxygen task as shown below: Lets run the target again and see if it fixed things.Yes indeed. generate-doxygen-docs: [doxygen] Exec: /Applications/Doxygen.app/Contents/Resources/doxygen reports/Doxyfile BUILD SUCCESSFUL Total time: 8 seconds 4. Integrate with Hudson. 4.a Modify Hudson Job. Once you have an Ant target working, calling this from your CI server is trivial. Within Hudson, select your Job, click on configure and add this new target to be called when running the build. 4.b Publish the reports. 4. c: Sample Reports. Force a build, and take a detailed look at the reports generated by Doxygen as shown below: I have given you a brief overview of Doxygen in this article, how to configure the same, and use it effectively to generate technical documentation on a continuous basis; either on commit builds or nightly builds. The Doxygen web site has lots of information on how to use it with other programming languages and also has tutorials in languages other than English as well. As always, if you are having trouble getting Doxygen to work, leave a comment or check out the Doxygen web site.
September 10, 2008
by Meera Subbarao
· 49,698 Views · 1 Like
article thumbnail
Reverse-Engineer Source Code into UML Diagrams
This article shows how easy and simple it is to include UML diagrams within your Javadoc and also keep them updated with every change in the source code repository.
August 22, 2008
by Meera Subbarao
· 220,874 Views · 1 Like
  • Previous
  • ...
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 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
×