TomcatExpert

Case Study: Hyperic Goes Lean with Spring & Apache Tomcat

posted by Stacey Schneider on November 29, 2010 01:03 PM

Last fall, software provider Hyperic started on a release plan that by all accounts is a major shift in infrastructure by migrating their EJB layer to Spring 3.0 and their internal server to Apache Tomcat. Originally built in 2002, and released as open source in 2006, the Hyperic software, a web infrastructure monitoring and management application, helps some of the largest web shops in the world monitor and manage their production web applications. For any well established software, such a fundemental change to the application architecture is surely not a decision that was made lightly.

So Why Such The Change?

The obvious answer is to follow the proven mantra of eating your own dog food. In 2009, Hyperic was acquired by SpringSource, who has significant investment in both their flagship product Spring and the Apache Tomcat, through their commercial distribution of Tomcat, vFabric tc Server, and the number of Tomcat committers and experts employed directly by the company. By adopting the "company standards", they have better access to engineering support and follow software best practices of using their products just like their customers do.

However, with such an established code base and number of production customers, a shift of this magnitude is bound to delay the development of new features and potentially bug fixes, which are critical improvements needed to keep customers happy. This type of a decision therefore needs to translate quickly into financial or customer benefit.

So why the change? The answer is the Hyperic engineering team wanted to move towards lean software development, a system of development processes popular with the Agile development community. The result of the move would allow future development and bug fixes of the product to happen more quickly through simpler configuration, reduced code complexity, decreased application start time, and faster debugging process which improves the maintainability, testibility, and reliability and their Hyperic HQ 4.5 software, which was released this month. In essence, a temporary delay on a stable product release would quickly pay dividends to their development costs and ultimately provide faster development of features for their customers.

For more information on the rationale, and a detailed walk through of the migration itself, check out the complete webinar that Hyperic technical lead, Jennifer Hickey originally delivered at the SpringOne 2GX conference held in Chicago in October. A link to an audio recording of her presentation with her original slides can be found in the Knowledge Based section of the Tomcat Community here: Hyperic's Migration to Spring and Apache Tomcat Case Study presentation.

Since the presentation is 71 pages and the webinar is 1 hour and 18 minutes, we've taken the liberty of summarizing some of Jennifer's favorite benefits of the migration as originally posted in Jennifer's blog post on the SpringSource team blog.

==================================================================

Improved testability

Switching to Spring allowed us to convert our existing Stateless Session EJBs to POJOs with autowired dependencies. This eliminated quite a bit of static JNDI lookup code that made unit testing so difficult. Spring also made integration testing significantly easier. Before the conversion, we had a handful of integration tests that each took several minutes to bootstrap an approximation of an EJB container. This process was cumbersome and error prone. Additionally, the tests often left the database in an inconsistent state, making it necessary to add database setup or tear down code, adding additional overhead to test execution time and occasionally causing inconsistent test results.

After the conversion, we were able to take advantage of Spring's integration testing support to test our new service layer of converted EJBs as well as their underlying DAOs. By simply adding a few annotations, we were able to bootstrap our entire application context in less than 30 seconds and run each test method in a dedicated transaction that was automatically rolled back at the end of the test. This support proved very valuable in allowing us to quickly increase our test coverage by 18% and 12% in our open source and enterprise codebases respectively.

{code}
   @Transactional
   @RunWith(SpringJUnit4ClassRunner.class)
   @ContextConfiguration(locations = "classpath*:META-INF/spring/*-context.xml")
   public class AppdefManagerTest  {
 
@Autowired
   private AppdefManager appdefManager;
 
@Before
   public void setUp() throws Exception {
   createPlatformType("TestPlatform", "test");
   }
 
@Test
   public void testGetControllablePlatformTypes() throws Exception {
   Map<String, AppdefEntityID> platformTypes = appdefManager
   .getControllablePlatformTypes(subject);
   assertEquals(1, platformTypes.size());
   assertEquals("TestPlatform", platformTypes.keySet().iterator().next());
   }
 
}
   {code}

Reduced code complexity

Simply introducing Spring for dependency injection greatly simplified the code in many areas by eliminating verbose dependency lookup. However, there are many other places where introduction of Spring significantly improved the clarity of code, reducing the clutter of infrastructure and allowing us to focus on the true business logic. Two of my favorite examples of this in Hyperic are the usage of JmsTemplate for publishing JMS messages and JdbcTemplate for data access.

Message Publishing Before
{code}
public void publishMessage(String name, Serializable sObj) {
TopicConnection conn = null;
TopicSession session = null;
if (_ic == null)
_ic = new InitialContext();
if (_factory == null)
_factory = _ic.lookup(CONN_FACTORY_JNDI);
TopicConnectionFactory tFactory = (TopicConnectionFactory) _factory;
Topic topic = getTopic(name);
if (topic != null) {
// Now create a connection to send a message
if (_tConn != null)
conn = _tConn;
else
conn = tFactory.createTopicConnection();
if (conn == null)
_log.error("TopicConnection cannot be created");
if (_tSession != null)
session = _tSession;
else
session = conn.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);
// Create a publisher and publish the message
TopicPublisher publisher = session.createPublisher(topic);
ObjectMessage msg = session.createObjectMessage();
msg.setObject(sObj);
publisher.publish(msg);
...
}
{code}
Message Publishing After
{code}
	public void publishMessage(String name, Serializable sObj) {
	eventsJmsTemplate.convertAndSend(name, sObj);
	}
	{code}
Data Access Before
{code}
	public int getServicesCount(AuthzSubject subject) {
	Statement stmt = null;
	ResultSet rs = null;
	Integer subjectId = subject.getId();
	try {
	Connection conn = getDBConn();
	String sql = "SELECT COUNT(SVC.ID) FROM TBL_SERVICE";
	stmt = conn.createStatement();
	rs = stmt.executeQuery(sql);
	if (rs.next()) {
	return rs.getInt(1);
	}
	} catch (SQLException e) {
	log.error("Caught SQL Exception finding Services by type: " + e, e);
	throw new SystemException(e);
	} finally {
	DBUtil.closeJDBCObjects(LOG_CTX, null, stmt, rs);
	}
	return 0;
	}
	{code}
Data Access After
{code}
	public int getServicesCount(AuthzSubject subject) {
	return jdbcTemplate.queryForInt("SELECT COUNT(SVC.ID) FROM TBL_SERVICE");
	}
	{code}

That's quite a weight loss plan! Simply by converting to Spring and not changing any functionality, we reduced both the open source and enterprise codebases by approximately 7%.

Improved developer productivity

As mentioned above, the Spring support for integration testing allows us to bootstrap our entire application context in less than 30 seconds for end-to-end integration testing. This has been a huge time-saver when testing new features or debugging problems. When we do need to bring up the entire web application, the switch to Tomcat has improved our productivity by significantly decreasing startup time. A single developer coding and debugging an application now saves approximately 5 minutes of waiting each time he/she starts up the application. Considering that developer may restart the application 12 times a day, that frees up an entire hour per day to develop new features! Additionally, the cleaner code and improved unit testability has made it faster and easier to find and fix problems, and the flexible architecture makes it easier to add new features and enhancements.

==================================================================

Also in keeping with the eating your own dog food theme, the new open sourch Hyperic HQ 4.5 and enterprise vFabric Hyperic 4.5 include support for 3 more SpringSource owned software products, including vFabric GemFire 6.5 distributed caching system, RabbitMQ enterprise messaging system, and the new vFabric tc Server 2.1 Java runtime server also released this week.

Stacey Schneider is focused on helping evangelize how cloud technologies are transforming application development and delivery by managing the blog and social media for Pivotal. Prior to its acquisition, Stacey led marketing and community management for application management software provider Hyperic, now a part of VMware’s management portfolio. Before her work in the cloud, she also held various technical leadership positions at CRM software pioneer Siebel Systems, including work on the Nexus project, which focused on building portable web applications that worked across Java and .NET. Stacey is also the managing principal of SiliconSpark, a consulting agency that has helped over 12 software companies go to market on the web and across the cloud over the past 5 years.

Comments

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.