The most telling aspect or area where Java Developers & for that matter the architects, are heavily tested is developing and designing middleware & server-side components.And I have developed many such kind of applications using EJB in the past.And even though there has been lot of growth from EJB2.1 to EJB3.0 specifications(particularly,annotations),the areas where personally I had a hard time using it has been unit testing the code and implementing effective transaction management.Some might argue ,Iam blaming it because I cant use it effectively and Iam not at all questioning its virtue and value and Iam still and will use it,being a standard framework defined by the Java Community Process (JCP) and supported by all major J2EE vendors,my focus is how best other lightweight solutions like Spring,Hibernate or for that matter Google Guice(even though I didnt get an opportunity to use & implement Guice in any enterprise applications so far),has made my life easier with respect to TDD and implementing Transaction management,security and persistence in distributed computing.
Lightweight vs Heavyweight frameworks
A software framework is a re-usable design for a software system (or subsystem). A software framework may include support programs, code libraries, a scripting language, or other software to help develop and glue together the different components of a software project. Various parts of the framework may be exposed through an API.
Lightweight framework : Applications developed using lightweight framework do not have to depend on framework interfaces or abstract classes to "hook" components into the application in which category frameworks like Spring,Google Guice fall into compared to Heavyweight frameworks ,that require the extension of framework classes or the implementation of framework interfaces in order to take advantage of their middleware features. EJB2 is probably the most popular example of a heavyweight framework(And I do know the growth and support in EJB3 for POJOs,discussed later,which makes it lightweight and starting to become popular because of EJB3 Annotations along with JPA ).EJB is a heavyweight model for objects that don’t need to offer remote access.
Test first development has become much more popular in the last few years, and usually produces impressive results. Writing effective unit tests for an application isn’t just a question of putting in the time and effort; it can be severely constrained by high-level architecture. This is one of the biggest frustrations with EJB. Due to its heavy dependence on the EJB container, business logic coded in EJB is very hard to test.Code that is hard to test is usually also hard to re-engineer, reuse in different contexts, and refactor(though one might argue with me citing the existence of lightweight frameworks like MockEJB)and considering testability is an essential characteristic of agile projects.
Spring Framework
Spring is an open source project led by SpringSource & Interface21 and brainchild of Rod Johnson.Spring is a light-weight framework for the development of enterprise-ready applications. Spring can be used to configure declarative transaction management, remote access to your logic using RMI or web services, mailing facilities and various options in persisting your data to a database. Spring framework can be used in modular fashion, it allows to use in parts and leave the other components which is not required by the application.The Spring framework is a layered architecture consisting of seven well-defined modules.Here is a brief description of the seven modules,
Inversion of Control (IoC) Container: Also called the Core Container, creates and configures application objects and wires them together. This means that resources and collaborating objects are provided to objects, so the objects do not need to look them up. This moves an important responsibility out of your code and makes it easier to write and test code.
Aspect-Oriented Programming (AOP) framework:Works with cross-cutting concerns—one solution to a problem that’s used in multiple places. The Spring AOP framework links cross-cutting concerns to the invocation of specific methods on specific objects (not classes) in such a way
that your code is unaware of their presence. The Spring Framework uses cross-cutting concerns and AOP to let your application deal with transactions without having a single line of transaction management code in your code base.
Data Access framework: Hides the complexity of using persistence APIs such as JDBC,Hibernate, and many others. Spring solves problems that have been haunting data-access developers for years: how to get hold of a database connection, how to make sure that the connection is closed, how to deal with exceptions, and how to do transaction management. When using the Spring Framework, all these issues are taken care of by the framework.
Transaction Management framework: Provides a very efficient way to add transaction management to your applications without affecting your code base. Adding transaction management is a matter of configuration, and it makes the lives of application developers much easier.Spring Framework simplifies it dramatically.And along with Unit Testing,this is the area I would be dwelling upon here.
Resource Abstraction framework: Offers a wonderful feature for conveniently locating files when configuring your applications. Chapter 2 discusses resource abstraction.
Validation framework: Hides the details of validating objects in web applications or rich client applications. It also deals with internationalization (i18n) and localization (l10n).
Spring Web MVC(Another significant framework,one of my fav): Provides a Model-View-Controller (MVC) framework that lets you build powerful web applications with ease. It handles the mapping of requests to controllers and of controllers to views. It has excellent form-handling and form-validation capabilities, and integrates with all popular view technologies, including JSP, Velocity, FreeMarker, XSLT,JasperReports, Excel, and PDFs.
Spring Web Flow:Makes implementing web-based wizards and complex workflow processes very easy and straightforward. Spring Web Flow is a conversation-based MVC framework.Spring Web Flow is distributed separately and can be downloaded via the Spring Framework website.
Acegi Security System: Adds authentication and authorization to objects in your application using AOP. Acegi can secure any web application, even those that do not use the Spring Framework.It offers a wide range of authentication and authorization options that will fit your most exotic security needs. Adding security checks to your application is straightforward and a
matter of configuration; you don’t need to write any code, except in some special use cases.Acegi is distributed separately and can be downloaded from http://acegisecurity.org/downloads.html.
Remote Access framework: Adds client-server capabilities to applications through configuration.Objects on the server can be exported as remotely available services. On the client, you can call these services transparently, also through configuration. Remotely accessing services
over the network thus becomes very easy. Spring’s Remote Access framework supports HTTPbased protocols and remote method invocation (RMI), and can access Enterprise JavaBeans as a client.
Spring Web Services: Takes the complexity out of web services and separates the concerns into manageable units. Most web service frameworks generate web service end points and definitions based on Java classes, which get you going really fast, but become very hard to manage as your project evolves. To solve this problem, Spring Web Services takes a layered approach and
separates the transport from the actual web service implementation by looking at web services as a messaging mechanism. Handling the XML message, executing business logic, and generating an XML response are all separate concerns that can be conveniently managed. Spring Web Services is distributed separately and can be downloaded via the Spring Framework website
Spring JMX: Exports objects via Java Management Extensions (JMX) through configuration.Spring JMX is closely related to Spring’s Remote Access framework. These objects can then be managed via JMX clients to change the value of properties, execute methods, or report statistics.
JMX allows you to reconfigure application objects remotely and without needing to restart the application.
OK lets start exploring the easiness ,robustness & scalability features being supported by Spring in Unit Testing and Transaction Management of the enterprise applications.
Test Driven Development with Spring Framework
To understand its use, we need to know what a POJO(Plain Old Java Object) is,POJO is a Java Object that doesn't implement any special interfaces or call any framework classes,remember the definition of Lightweight Framework.The benefits of POJO comes from decoupling the application code from the infrastructure frameworks.POJOs accelerate development, we can test our business logic outside of the application server(important criteria in TDD) and without a database.We dont have to package the code and deploy it in the application server and also we dont have to keep the database schema constantly in sync with the object model or spend time waiting for slow-running database tests to finish.
The Spring framework,provides services for POJOs such as transaction management,dependency injection,support for POJO remoting and security for POJOs(Acegi).
Dependency Injection
Dependency Injection is one of the core features of Spring Framework.
Dependency injection (DI) refers to the process of supplying an external dependency to a software component and is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency.
Conventionally, if an object needs to gain access to a particular service, the object takes responsibility to get hold of that service: either it holds a direct reference to the location of that service, or it goes to a known 'service locator' (in EJB2)and requests that it be passed back a reference to an implementation of a specified type of service. By contrast, using dependency injection, the object simply provides a property that can hold a reference to that type of service; and when the object is created a reference to an implementation of that type of service will automatically be injected into that property - by an external mechanism. The dependency injection approach offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a mock implementation of a service into the object being tested. On the other hand, excessive use of dependency injection can make applications more complex and harder to maintain: in order to understand the application's behaviour the developer needs to look at the configuration as well as the code, and the configuration is "invisible" to IDE-supported reference analysis and refactoring unless the IDE specifically supports the dependency injection framework.To use it,you must configure Spring's bean factory
Benefits of Dependency Injection
It eliminates the need to call lookup APIs,because a components dependencies are passed to it,we no longer have to write tedious JNDI code and components depend mainly on interfaces rather than on concrete implementations.
Types of dependency injection
Constructor injection,setter&getter injection and Method injection.
Spring’s org.springframework.test package has
number of base classes to simplify testing.
AbstractDependencyInjectionSpringContextTests - can do both setter or field-based dependency injection,cached context files
AbstractTransactionalDataSourceSpringContextTests -
allows you to easily clear data from tables and rolls back any data entered into the database.
Testing approaches
Generally speaking, testing should be used to ensure the following aspects of an application:
Correctness: You want to ensure the correctness of your application. For example, suppose that you have written a calculate() method on a Calculator class. You want to make sure that certain input for this method results in a correct calculation result.
Completeness: Testing can be used to ensure that your application is complete by verifying that all required operations have been executed. Suppose you have a signup process that includes creating an invoice for newly signed-up members. You want to test whether a member is actually added to the database, and also if an invoice has been created for that user.
Quality: Testing can ensure the quality of your application, and this goes beyond software quality metrics. A well-tested piece of software creates confidence with developers. When existing code needs to be changed, it’s less likely that developers will be afraid of unintentionally
breaking the software or reintroducing bugs.
Unit Testing
This so-called plain old Java object (POJO) approach to Java coding, combined with defining interfaces for important parts of your application provides the basis for thorough testing. The Spring Framework promotes exactly this approach (we could also say the Spring Framework makes this approach possible). By separating your code into well-defined interfaces and objects, you have already defined the units that are eligible for unit testing.
One goal of unit testing is to ensure that each unit of an application functions correctly in isolation.Another goal is to define a framework, harness, or contract (all referring to a strict set of rules that must be respected) that must be satisfied by the unit test. As long as the tests can be run successfully,
the unit is considered to work properly. (If there are bugs in the test code, the unit will function properly according to this buggy test code.)
Unit testing offers a number of benefits for developers:
Facilitate change: As previously mentioned, having a set of unit tests for a specific piece of code provides confidence in refactoring existing code. The unit tests will ensure the module continues to function correctly according to the available tests as long as the tests succeed.
Given there are enough tests for all the code in the application, this promotes and facilitates changing implementation details of units in the application. An important aspect of facilitating change is preventing solved problems or bugs from reentering the code.
Simplify integration: Unit testing provides a bottom-up testing approach, which ensures that low-level units function properly according to their tests. This makes it easier to write integration tests at a later stage. There is no need to have two tests for units.
Promote well-defined separation: In order for you to be able to completely and efficiently write unit tests, your code needs to be separated into well-defined units. Each unit needs to be tested in isolation and should therefore allow the replacement of dependencies with test specific ones. Thus, writing unit tests promotes the separation of your application into well-defined units.
Test-driven development (TDD) is a way of implementing code by writing a unit test before implementing the actual class.
Using Spring for Testing
When working with Spring for building your applications, you will typically use one or more XML configuration files for defining your application context. These configuration files are not Java files and will therefore not be compiled. Of course, if you include the Spring DTD or use Spring’s namespace support, some aspects of your configuration files will be validated. But issues such as defining a nonexisting class as the class for a bean in your application context or setting a nonexisting property on a bean definition are discovered only when you actually load the application context at runtime. This is where integration testing comes into the picture.The goal of integration testing is to test how the individually tested units of your application collaborate with each other. When working with Spring, you wire those dependencies together using Spring’s configuration files. In order to test part of your whole application, you typically want to load the Spring application context and test one or more beans configured in that application.
Spring provides three convenient test base classes for integration testing of your Spring applications: AbstractDependencyInjectionSpringContextTests, AbstractTransactionalSpringContextTests, and AbstractTransactionalDataSourceSpringContextTests. These classes are discussed in the following sections.
The org.springframework.test.AbstractDependencyInjectionSpringContextTests base class is the test class you will typically use when testing parts of your application that do not require access to a database or any other transactional support. You should extend this class by first implementing the getConfigLocations() method, which should return an array of application context locations to be loaded by the test. When the test is executed, the specified configurations will be loaded as an application context.
The major advantage of using this base class is that the application context will be loaded only once for each test method. If you were to load the application yourself in the setUp() method of a test, the application context would be reloaded for every test method. This is especially useful when loading configurations that require a lot of initialization, such as a Hibernate session factory.
Another convenient test base class is org.springframework.test.AbstractTransactionalSpringContextTests, which builds on top of the functionality offered by the AbstractDependencyInjectionSpringContextTests test base class. Each test method that is executed by a subclass of this base class will automatically participate in a transaction. Because the default is to roll back
the transaction after each test method execution, no actual modifications will be made to any transactional resources. This makes it the perfect choice for performing integration tests using a transactional data source.
Using this base class allows you to integration test functionality that will make modifications to the database without having to worry about the changes affecting any other test methods. It also allows you test code that requires a transactional context. And you can write data to the database without worrying about cleaning it up afterwards.As mentioned, all modifications to the database are rolled back at the end of each test method execution.
A third convenient test base class is org.springframework.test.AbstractTransactionalDataSourceSpringContextTests, which builds on top of the functionality provided by AbstractTransactional
SpringContextTests. In order to use this base class, you need to include a DataSource definition in the application context loaded by this test. The data source is automatically injected, as explained earlier.
The main feature offered by this base class is that it provides you with a JdbcTemplate as a protected field, which you can use to modify the data source, within the transactional context. You could, for instance, insert some data that the test needs in order to succeed. Because the statements to the JdbcTemplate are also executed within the transactional context, you do not need to worry about cleaning up the database or modifying the existing data.Another advantage of using this base class is that you can define fields for this test that are populated
automatically by Spring based on your application context.Spring also provides support for testing your J2EE-specific application code. Because much of your web application code is very much tied to J2EE classes, it is hard to test. For instance, testing a servlet or a Spring controller implementation requires you to somehow mock the HttpServletRequest and HttpServletResponse classes.
Transaction Management using Spring
Two main issues make database transactions complicated for developers to work with and difficult for database vendors to implement:
Concurrency control: Databases need to protect against data loss or ghost data, yet allow concurrent access to the same data. Generally, developers can choose an isolation level to control the level of protection. Another form of concurrency control is protecting against lost updates.
Synchronization between transactions: Complex applications often need a way to synchronize two or more databases or other resources so that their local transactions are guaranteed to commit or roll back in a group. The technique used for this is called two-phase commit (or 2PC), distributed transactions, or global transactions.
The first step in setting up transaction management with Spring is choosing a transaction management strategy. This basically means selecting which of the transaction-management APIs in Java you want to use.The main interface of this API is org.springframework.transaction.PlatformTransactionManager.
Spring provides a number of implementations of this interface that support the most popular transaction-management APIs in Java.Like,org.springframework.jdbc.datasource. DataSourceTransactionManager,org.springframework.orm.hibernate.HibernateTransactionManager
org.springframework.orm.hibernate3.HibernateTransactionManager.
The Spring Bean factory does more than simply instantiate objects.It can also wrap the objects that it creates with interceptors.These interceptors are how Spring provides a simple,yet effective AOP(Aspect-Oriented Programming)implementation.AOP is the foundation of Spring Transaction Management.To make a POJO transactional you configure the bean factory to wrap it with TransactionInterceptor.One option is to use the @Transactional annotation on the interace,implementation class or individual methods.Another option is to write XML bean definitions that explicitly apply the TransactionInterceptor to the POJO.The XML is more verbose than the annotation but has the advantage of leaving the source code unchanged.It also works with older JDKs that dont' support annotations.
Spring doesn't implement transactions itself but is,instead, a wrapper around other transaction management APIs.Unlike EJB3,it gives you the flexibility of using either JTA or the transaction management APIs provided by ORM frameworks such as Hibernate.
In the next article of this series,we will explore more about Transaction Management in Spring and as well as AOP(Aspect Oriented Programming).
Suggested Video Tutorial
Spring 2.x by Rod Johnson (Founder of Spring framework)
Integration Testing with Spring by Rod Johnson
Spring vs EJB3.0 by Debu Panda
Spring Experience Video by Adrian Colyer Adrian Colyer is the leader of the AspectJ open source project and a well-known industry expert on the topic of aspect-oriented programming (AOP)
Suggested Reading:
http://java.sys-con.com/read/180374.htm
http://static.springframework.org/spring/docs/2.5.1/reference/testing.html
http://static.springframework.org/spring/docs/1.2.x/reference/transaction.html
http://mike.hostetlerhome.com/2007/07/06/easier-unit-testing-in-spring/
http://dev2dev.bea.com/pub/a/2005/07/spring_transactions.html
Recommended Books
You can get this book from Here Print this post
0 comments:
Post a Comment