, ,

I have met many developers who refer to tests as “Unit Tests” when they are actually integration tests. In service layers, I’ve seen tests referred as unit tests, but written with dependencies on the actual service, such as a database, web service, or some message server. Those are part of integration testing. Even if you’re just using the Spring Context to auto-wire dependencies, your test is an integration test. Rather than using the real services, you can use Mockito mocks and spies to keep your tests unit tests and avoid the overhead of running integration tests.

This is not to say Integration tests are bad. There is certainly a role for integration tests. They are a necessity.

But compared to unit tests, integration tests are sloooowwwww. Very slow. Your typical unit test will execute in a fraction of a second. Even complex unit tests on obsolete hardware will still complete sub-second.

Integration tests, on the otherhand take several seconds to execute. It takes time to start the Spring Context. It takes time to start a H2 in memory database. It takes time to establish a database connection.

While this may not seem much, it becomes exponential on a large project. As you add more and more tests, the length of your build becomes longer and longer.

No developer wants to break the build. So we run all the tests to be sure. As we code, we’ll be running the full suite of tests multiple times a day. For your own productivity, the suite of tests needs to run quickly.

If you’re writing Integration tests where a unit test would suffice, you’re not only impacting your own personal productivity. You’re impacting the productivity of the whole team.

On a recent client engagement, the development team was very diligent about writing tests. Which is good. But, the team favored writing Integration tests. Frequently, integration tests were used where a Unit test could have been used. The build was getting slower and slower. Because of this, the team started refactoring their tests to use Mockito mocks and spies to avoid the need for integration tests.

They were still testing the same objectives. But Mockito was being used to fill in for the dependency driving the need for the integration test.

For example, Spring Boot makes it easy to test using a H2 in memory database using JPA and repositories supplied by Spring Data JPA.

But why not use Mockito to provide a mock for your Spring Data JPA repository?

Unit tests should be atomic, lightweight, and fast that are done as isolated units. Additionally, unit tests in Spring should not bring up a Spring Context. I have written about the different types of tests in my earlier Testing Software post.

I have already written a series of posts on JUnit and a post on Testing Spring MVC With Spring Boot 1.4: Part 1. In the latter, I discussed unit testing controllers in a Spring MVC application.

I feel the majority of your tests should be unit tests, not integration tests. If you’re writing your code following the SOLID Principles of OOP, your code is already well structured to accept Mockito mocks.

In this post, I’ll explain how to use Mockito to test the service layer of a Spring Boot MVC application. If Mockito is new for you, I suggest reading my Mocking in Unit Tests With Mockito post first.

Using Mockito Mocks and SpiesMockito Mocks vs Spies

In unit test, a test double is a replacement of a dependent component (collaborator) of the object under test. The test double does not have to behave exactly as the collaborator. The purpose is to mimic the collaborator to make the object under test think that it is actually using the collaborator.

Based on the role played during testing, there can be different types of test doubles. In this post we’re going to look at mocks and spies.

There are some other types of test doubles, such as dummy objects, fake objects, and stubs. If you’re using Spock, one of my favorite tricks was to cast a map of closures in as a test double. (One of the many fun things you can do with Groovy!)

What makes a mock object different from the others is that it has behavior verification. Which means the mock object verifies that it (the mock object) is being used correctly by the object under test. If the verification succeeds, you can conclude the object under test will correctly use the real collaborator.

Spies on the other hand, provides a way to spy on a real object. With a spy, you can call all the real underlying methods of the object while still tracking every interaction, just as you would with a mock.

Things get a bit different for Mockito mocks vs spies. A Mockito mock allows us to stub a method call. Which meams we can stub a method to return a specific object. For example, we can mock a Spring Data JPA repository in a service class to stub a getProduct() method of the repository to return a Product object. To run the test, we don’t need the database to be up and running – a pure unit test.

A Mockito spy is a partial mock. We can mock a part of the object by stubbing few methods, while real method invocations will be used for the other. By saying so, we can conclude that calling a method on a spy will invoke the actual method, unless we explicitly stub the method, and therefore the term partial mock.

Let’s look mocks vs spies in action, with a Spring Boot MVC application.

The Application Under Test

Our application contains a single Product JPA entity. CRUD operations are performed on the entity by ProductRepository using a CrudRepository supplied by Spring Data JPA. If you look at the code, you will see all we did was extend the Spring Data JPA CrudRepository to create our ProductRepository. Under the hood, Spring Data JPA provides implementations to manage entities for most common operations, such as saving an entity, updating it, deleting it, or finding it by id.

The service layer is developed following the SOLID design principles. We used the “Code to an Interface” technique, while leveraging the benefits of dependency injection. We have a ProductService interface and a ProductServiceImpl implementation. It is this ProductServiceImpl class that we will unit test.

Here is the code of ProductServiceImpl .

ProductServiceImpl.java

In the ProductServiceImpl class, you can see that ProductRepository is @Autowired in. The repository is used to perform CRUD operations. – a mock candidate to test ProductServiceImpl.

Testing with Mockito Mocks

Coming to the testing part, let’s take up the getProductById() method of ProductServiceImpl. To unit test the functionality of this method, we need to mock the external Product and ProductRepository objects. We can do it by either using the Mockito’s mock() method or through the @Mockito annotation. We will use the latter option since it is convenient when you have a lot of mocks to inject.

Once we declare a mock` with the @Mockito annotation, we also need to initialize it. Mock initialization happens before each test method. We have two options – using the JUnit test runner, MockitoJUnitRunner or MockitoAnnotations.initMocks() . Both are equivalent solutions.

Finally, you need to provide the mocks to the object under test. You can do it by calling the setProductRepository() method of ProductServiceImpl or by using the @InjectMocks annotation.

The following code creates the Mockito mocks, and sets them on the object under test.

Note: Since we are using the Spring Boot Test starter dependency, Mockito core automatically is pulled into our project. Therefore no extra dependency declaration is required in our Maven POM.

Once our mocks are ready, we can start stubbing methods on the mock. Stubbing means simulating the behavior of a mock object’s method. We can stub a method on the ProductRepository mock object by setting up an expectation on the method invocation.

For example, we can stub the findOne() method of the ProductRepository mock to return a Product when called. We then call the method whose functionality we want to test, followed by an assertion, like this.

This approach can be used to test the other methods of ProductServiceImpl, leaving aside deleteProduct() that has void as the return type.

To test the deleteProduct(), we will stub it to do nothing, then call deleteProduct(), and finally assert that the delete() method has indeed been called.

Here is the complete test code for using Mockito mocks:

ProductServiceImplMockTest.java

Note: An alternative to doNothing() for stubbing a void method is to use doReturn(null).

Testing with Mockito Spies

We have tested our ProductServiceImpl with mocks. So why do we need spies at all? Actually, we don’t need one in this use case.

Outside Mockito, partial mocks were present for a long time to allow mocking only part (few methods) of an object. But, partial mocks were considered as code smells. Primarily because if you need to partially mock a class while ignoring the rest of its behavior, then this class is violating the Single Responsibility Principle, since the code was likely doing more than one thing.

Until Mockito 1.8, Mockito spies were not producing real partial mocks. However, after many debates & discussions, and after finding a valid use case for partial mock, support for partial mock was added to Mockito 1.8.

You can partially mock objects using spies and the callRealMethod() method. What it means is without stubbing a method, you can now call the underlying real method of a mock, like this.

Be careful that the real implementation is ‘safe’ when using thenCallRealMethod(). The actual implementation needs be able to run in the context of your test.

Another approach for partial mocking is to use a spy. As I mentioned earlier, all method calls on a spy are real calls to the underlying method, unless stubbed. So, you can also use a Mockito spy to partially mock few stubbed methods.

Here is the code provide a Mockito spy for our ProductServiceImpl .

ProductServiceImplSpyTest.java

In this test class, notice we used MockitoJUnitRunner instead of MockitoAnnotations.initMocks() for our annotations.

For the first test, we expected NullPointerException because the getProductById() call on the spy will invoke the actual getProductById() method of ProductServiceImpl, and our repository implementations are not created yet.

In the second test, we are not expecting any exception, as we are stubbing the save() method of ProductRepository.

The second and third methods are the relevant use cases of a spy in the context of our application– verifying method invocations.

Conclusion

In Spring Boot applications, by using Mockito, you replace the @Autowired components in the class you want to test with mock objects. In addition to unit test the service layer, you will be unit testing controllers by injecting mock services. To unit test the DAO layer, you will mock the database APIs. The list is endless – It depends on the type of application you are working on and the object under test. If your following the Dependency Inversion Principle and using Dependency Injection, mocking becomes easy.

For partial mocking, use it to test 3rd party APIs and legacy code. You won’t require partial mocks for new, test-driven, and well-designed code that follows the Single Responsibility Principle. Another problem is that when() style stubbing cannot be used on spies. Also, given a choice between thenCallRealMethod on mock and spy, use the former as it is lightweight. Using thenCallRealMethod on mock does not create the actual object instance but bare-bones shell instance of the Class to track interactions. However, if you use spy, you create an object instance. As regard spy, use it if you only if you want to modify the behavior of small chunk of API and then rely mostly on actual method calls.

The code for this post is available for download here.

1
Share
, ,

Unit tests should be small tests (atomic), lightweight, and fast. However, an object under test might have dependencies on other objects. It might need to interact with a database, communicate with a mail server, or talk to a web service or a message queue. All these services might not be available during unit testing. Even if they are available, unit testing the object under test along with its dependencies can take unacceptable amount of time. What if?

  • The web service is not reachable.
  • The database is down for maintenance.
  • The message queue is heavy and slow.

These all defeat the whole purpose of unit tests being atomic, lightweight, and fast. We want unit tests to execute in a few milliseconds. If the unit tests are slow, your builds become slow, which affects the productivity of your development team. The solution is to use mocking, a way to provide test doubles for your classes being tested.

If you’ve been following the SOLID Principles of Object Oriented Programming, and using the Spring Framework for Dependency Injection, mocking becomes a natural solution for unit testing. You don’t really need a database connection. You just need an object that returns the expected result. If you’ve written tightly coupled code, you will have a difficult time using mocks. I’ve seen plenty of legacy code which could not be unit tested because it was so tightly coupled to other dependent objects. This untestable code did not follow the SOLID Principles of Object Oriented Programming, nor did it utilize Dependency Injection.

Mock Objects: Introduction

In unit test, a test double is a replacement of a dependent component (collaborator) of the object under test. A test double provides the same interface as of the collaborator. It may not be the complete interface, but for the functionality required for the test. Also, the test double does not have to behave exactly as the collaborator. The purpose is to mimic the collaborator to make the object under test think that it is actually using the collaborator.

Based on the role played during testing, there can be different types of test doubles, and mock object is one of them. Some other types are dummy object, fake object, and stub.

What makes a mock object different from the others is that it uses behavior verification. It means that the mock object verifies that it (the mock object) is being used correctly by the object under test. If the verification succeeds, it can be considered that the object under test will correctly use the real collaborator.

Free Spring Tutorial
Check out my FREE Introduction to Spring course!

The Test Scenario

For the test scenario, consider a product ordering service. A client interacts with a DAO to fulfill a product ordering process.

We will start with the Product domain object and the DAO interface, ProductDao.

Product.java

ProductDao.java

For the purpose of the example, I kept the Product class empty. But in real applications, it will typically be an entity with states having corresponding getter and setter methods, along with any implemented behaviors.

In the ProductDao interface, we declared two methods:

  • The getAvailableProducts() method returns the number of available quantity of a Product passed to it.
  • The orderProduct() places an order for a product.

The ProductService class that we will write next is what we are interested on the object under test.

ProductService.java

The ProductService class above is composed of ProductDao, which is initialized through a setter method. In the buy() method, we called getAvailableProducts() of ProductDao to check if sufficient quantity of the specified product is available. If not, an exception of type InsufficientProductsException is thrown. If sufficient quantity is available, we called the orderProduct() method of ProductDao.

What we now need is to unit test ProductService. But as you can see, ProductService is composed of ProductDao, whose implementations we don’t have yet. It can be a Spring Data JPA implementation retrieving data from a remote database, or an implementation that communicates with a Web service hosting a cloud-based repository – We don’t know. Even if we have an implementation, we will use it later during integration testing, one of the software testing type I wrote earlier on. But now, we are not interested on any external implementations in this unit test.

In unit tests, we should not to be bothered what the implementation is doing. What we want is to test that our ProductService is behaving as expected and that it is able to correctly use its collaborators. For that, we will mock ProductDao and Product using Mockito.

The ProductService class also throws a custom exception, InsufficientProductsException. The code of the exception class is this.

InsufficientProductsException.java

Using Mockito

Mockito is a mocking framework for unit tests written in Java. It is an open source framework available at github. You can use Mockito with JUnit to create and use mock objects during unit testing. To start using Mockito, download the JAR file and place it in your project class. If you are using Maven, you need to add its dependency in the pom.xml file, as shown below.

pom.xml

Once you have set up the required dependencies, you can start using Mockito. But, before we start any unit tests with mocks, let’s have a quick overview of the key mocking concepts.

Mock Object Creation

For our example, it’s apparent that we need to mock ProductDao and Product. The simplest way is through calls to the mock() method of the Mockito class. The nice thing about Mockito is that it allows creating mock objects of both interfaces and classes without forcing any explicit declarations.

MockCreationTest.java

An alternative way is to use the @Mock annotation. When you use it, you will need to initialize the mocks with a call to MockitoAnnotations.initMocks(this) or specify MockitoJUnitRunner as the JUnit test runner as @RunWith(MockitoJUnitRunner.class).

MockCreationAnnotationTest.java

Stubbing

Stubbing means simulating the behavior of a mock object’s method. We can stub a method on a mock object by setting up an expectation on the method invocation. For example, we can stub the getAvailableProducts() method of the ProductDao mock to return a specific value when the method is called.

In Line 4 of the code above, we are stubbing getAvailableProducts(product) of ProductDao to return 30. The when() method represents the trigger to start the stubbing and thenReturn() represents the action of the trigger – which in the example code is to return the value 30. In Line 5 with an assertion, we confirmed that the stubbing performed as expected.

Verifying

Our objective is to test ProductService, and unitl now we only mocked Product and ProductDao and stubbed getAvailableProducts() of ProductDao.

We now want to verify the behavior of the buy() method of ProductService. First, we want to verify whether it’s calling the orderProduct() of ProductDao with the required set of parameters.

In Line 6 we called the buy() method of ProductService that is under test. In Line 7, we verified that the orderProduct() method of the ProductDao mock get’s invoked with the expected set of parameters (that we passed to buy()).

Our test passed. But, not complete yet. We also want to verify:

  • Number of invocations done on a method: The buy() method invokes getAvailableProduct() at least once.
  • Sequence of Invocation: The buy() method first invokes getAvailableProduct(), and then orderProduct().
  • Exception verification: The buy() method fails with InsufficientProductsException if order quantity passed to it is more than the available quantity returned by getAvailableProduct().
  • Behavior during exception: The buy() method doesn’t invokes orderProduct() when InsufficientProductsException is thrown.

Here is the complete test code.

ProductServiceTest.java

I have already explained the initial code of the test class above. So we will start with Line 36 – Line 38 where we used the inOrder() method to verify the order of method invocation that the buy() method makes on ProductDao.

Then we wrote a purchaseWithInsufficientAvailableQuantity() test method to check whether an InsufficientProductsException gets thrown, as expected, when an order with quantity more than the available quantity is made. We also verified in Line 54 that if InsufficientProductsException gets thrown, the orderProduct() method is not invoked.

The output of the test is this.

Mockito Mocks vs Mockito Spies

In testing Spring Boot applications sometimes you need to access the real component. This is where Mockito Spies come into the picture. If you’d like to learn more about using Mockito Spies, check out this post.

Summary

Mocking in unit testing is extensively used in Enterprise Application Development with Spring. By using Mockito, you can replace the @Autowired components in the class you want to test with mock objects. You will be unit testing controllers by injecting mock services. You will also be setting up services to use mock DAOs to unit test the service layer. To unit test the DAO layer, you will mock the database APIs. The list is endless – It depends on the type of application you are working on and the object under test. If you’re following the Dependency Inversion Principle and using Dependency Injection, mocking becomes easy.

The Mockito library is a very large and mature mocking library. It is very popular to use for mocking objects in unit tests. Mockito is popular because it is easy to use, and very versatile. I wrote this post as just an introduction to mocking and Mockito. Checkout the official Mockito documentation to learn about all the capabilities of Mockito.

Free Spring Tutorial
Check out my FREE Introduction to Spring course!
7
Share
, ,

One of the things I wish to do on this blog is show you realistic examples of using the Spring Framework in Enterprise Application Development. The Spring Framework is very popular for building large scale applications. When you build a ecommerce website that might have 50,000 users on it at any given time the scope of the application you are building changes. This type of site quickly outgrows the traditional 3 tier architecture (web server / app server / database server). The ‘website’ is no longer a simple war file being deployed to Tomcat. You have a data center, with a small server farm. Load balancers, application clusters, message queuing, ‘cloud computing’, micro services. The Spring Framework was not only built for this type of application environment, it thrives in it.

Environments

When you start developing enterprise class applications, you will need to support multiple deployment environments. You’re no longer going to be testing code on your laptop, then deploying it to the production server. Frequently in the enterprise, as a developer you won’t even have access to the production environment. Companies which need to comply with regulations such as SOX, PCI and/or SAS-70 will have specialized teams which will manage code deployments to their testing (QA/UAT) and production environments. This is known as segregation of duties. A very common business practice. From my personal experience it is more stringent in large financial enterprises than it is in retail organizations. Less so in smaller companies because they simply don’t have the resources to support specialized IT staffs.

More modern development cultures will be performing CI builds and automated deployments. Teams on the bleeding edge of modern software development might even be doing continuous deployments I feel continuous deployment is probably the holy grail of software engineering, but in reality it is as rare as a great white buffalo in the wild. I do hope to see more organizations adopt continuous deployments, but it does take a very disciplined organization to get there.

Each of these environments will have its own configuration needs. As the scope of your application grows, chances are the uniqueness of each environment will grow too. The Spring Framework has some outstanding tools which are used to manage the complexities of modern enterprise application development. First, let’s consider some common challenges in the types of environments you will need to support in a large enterprise application.

Local Development

This is your development environment, running from your laptop. This is an area I often see companies absolutely fail at. Your code should be able to run locally, without the need to connect to other servers in the enterprise. Ideally, you should be able to run the code on a plane at 30,000 without a wi-fi connection.

This means:

  • You cannot use an external database. You’re not going to use the Oracle development database.
  • No interaction with other web services.
  • No JMS (MQ Series, Active MQ, Oracle AQ, etc)
  • Your build artifacts need to be locally cached (hello Maven, Ivy!!)

The Grails team does an outstanding job of supporting a local development environment of of the box. When you run Grails in dev mode, it will automatically create an in memory H2 database. Hibernate is used to generate the database tables based on your domain classes.

Continuous Integration

Continuous Integration servers can be tricky little beasts to configure for because of the different types of testing software they accomodate. You may have a project the produces a JAR file, which only has unit tests which will zip right along. You may have integration tests, like Grails does, which bring up an embedded Tomcat instance an H2 in-memory database. Your tests might even perform functional tests using something like Spock and Geb to interact with the embedded Tomcat instance. Its also not uncommon for CI servers to have automated deployment jobs – to another specialized environment.

Each of these scenarios is likely to drive special configuration needs into your application.

Development

Some companies elect to have a development environment. This is typically a production like server environment that the development team has control over. When you deploy into this environment, you will need to configure the application to interact with servers within that environment.

QA / UAT

QA or “Quality Assurance” and UAT “User Acceptance Testing” are environments for non-developer resources to test the software. In some organizations you may have both QA and UAT, or you might have one or the other. If you have both, chances are the organization has formal QA Engineers which work with the QA Environment, and Business Analysts which work with the UAT environment. These environments are often managed by a configuration management team. Sometimes developers will have access to the environment, but often they will not.

Pre-Production or Stage

Pre-Production or Stage (Staging) is an application environment that works with all the production services and supporting databases. This is an environment that allows the deployment of application code, but limits the access to that code. For a website, you might see a special url or access restricted to specific IPs, or throttled by load balancers.

This environment is not as common, but some organizations use it. Facebook deploys code something along this line.

Production

Production is the environment you end users will utilize. This is the main transactional environment and the one your business partners wish to keep operational at all times.

Summary

You can see each of these environments will have its own unique requirements. You’re going to have different database servers, different database versions, often different database vendors. You’ll have different supporting services. For example in an ecommerce website, you might have a payment gateway. In dev, it might be a mock, in test you might be using a testing gateway supplied by your payments provider, and then a different payment gateway for production.

Spring Framework Multi-Environment Support

The Spring Framework was developed from the ground up to support the challenges of supporting complex enterprise environments. You have a number of mature features in the Spring Framework to use in supporting the challenges of enterprise class applications.

Properties

The Spring Framework has excellent support of externalizing properties. “Properties” are simple string values which are externalized from your application. In the Spring Framework properties can be set the following ways:

  • In a traditional properties file. This is typically kept in the resources folder and is often named ‘application.properties’. It is by convention to use <filename>.properties.
  • Using Operating System Environment variables. Java can read values set in the Operating System as environment variables. I’ve used this in the past for things like database settings, which worked out nicely. In this case, my build artifact was easily portable between environments. Once setup, it was effectively ‘drag and drop’ for the support staff.
  • Command line variables. When starting any Java application, you have the opportunity to pass command line variables into the program. This is a handy way to make your build artifact portable. One word of caution, when examining running processes on a system, you can sometimes see the command line information which started the process. So this solution may not be the best option for password strings.

The Spring Framework Support has a number of options for sourcing in property values. One way is using the Spring Expression Language (SpEL). You can see some examples of this in my recent post here.

Dependency Injection

Changing property values is great for things like connecting to a different database server. But often in enterprise class applications you will need behavioral changes which are beyond simple property changes. One of the core features of the Spring Framework is the support of Dependency Injection. Once you become accustomed to development with Dependency Injection with in the Spring Framework, you will see how your code becomes more modular. Your classes will naturally adhere to the Single Responsibility Principle. If you’re doing Dependency Injection against Interfaces, it becomes very easy to swap out components.

Let’s say you have an application which needs to send a JMS message on an event such as a customer purchase. This may trigger an email to the customer about their order, and the data warehouse group might want the purchase information for their analytics. For your unit tests and your integration tests, you might be using Mockito to provide a mock. In your deployed environments you might be using the corporate standard of MQSeries for messaging. But what about doing CI builds? An embedded instance of ActiveMQ just might be perfect solution.

So, in summary, this example has:

  • A Mockito Mock object;
  • 3 different MQ Series configurations;
  • And embedded ActiveMQ.

The MQSeries configurations are easy to handle with property settings. The only thing changing here are the connection parameters. This is the perfect use case for externalized properties.

For your unit tests, if you want to keep them true unit tests (as I defined here), you’ll need to manage the dependency injection yourself. Testing frameworks such as Mocktio and Spock make this easy to do.

If you’re performing integration tests an easy way to manage the Spring Context is through configuration composition. But you may wish to favor using Spring Profiles instead. Each is easy to use, as I explain in the sections below.

Configuration Composition

Inexperienced Spring developers will place all their configuration into single xml files or configuration packages. This is often a mistake since it limits your configuration options. In our example, all of our configuration options could be supported through configuration composition. You would need to place each configuration into a separate xml file, or configuration package. Then selectivity import it into a parent configuration. You basically import the configuration you wish to use into a parent configuration, then load the parent into your Spring Context at run time. This is still a very popular technique to use for testing where it is very easy to specify the Spring context to use at runtime.

For a long time this was the only option Spring developers had to use. In Spring 3.1, Profiles were introduced to help manage different configurations. As you’ll see in the next section this a very powerful feature of Spring.

Spring Framework Profiles

Spring Profiles is a very powerful feature introduced in Spring Framework 3.1. Profiles allow you to define Spring Beans and specify when they should be loaded into the context.

If you do not mark your Spring Been with a profile, it will always be loaded into the Spring Context.

When you do mark your Spring Bean with a profile, then that profile must be set to active for that bean to be loaded into the Spring Context. This makes management of the environment easy, since you can simply mark the different options with the appropriate profile, then when you set that profile option to active, Spring will wire up the appropriate Spring Beans into your application.

There is one special profile that is rather poorly documented, but very nice to use. And that is the default profile. When you mark a Spring Bean using default , this bean is loaded into the context only if no other profile has been set to active. If it there is an active profile, Spring will attempt to find a bean matching that profile first.

What I like about using this option is you don’t have to set an active profile in production. While this is easy to use, from experience it can cause some friction and confusion with the configuration management team. Through the use of default profiles, your application can be deployed into production without an active profile being set.

Going back to the example we’ve been using, I would probably use a CI build profile for the CI build where I wanted to use an embedded instance of ActiveMQ, then setup the MQSeries option using the default profile. Having control over the CI build environment it’s easy for me to specify an active profile, so my CI build profile objects will get loaded into the Spring context. When my example application gets deployed elsewhere, no profile is set to active, so the default profile objects with the MQSeries configuration get loaded into the Spring Context. While we are supporting 3 different environments with MQSeries, this can be managed (and should be) with properties. This is because the MQSeries objects remain the same, except for the configuration of the environment the application is connecting to.

Conclusion

As an application developer, the Spring Framework offers you a lot of options on how you can compose your application. If you’re used to smaller scale development, the plethora of configuration options in the Spring Framework will probably seem like overkill to you. Why would you need such flexibility? Right? No, Wrong. As I’ve shown here, when developing applications in the enterprise you are going to be challenged with supporting the needs of many different environments. You are not just developing code on your laptop. No longer is the production environment the only environment you need to be concerned with. In a large enterprise you will need to support multiple environments, with different configurations and different needs. The Spring Framework has evolved over the years to support the challenging needs of enterprise application development. It’s no wonder that the Spring Framework is the most popular framework to use for developing enterprise class Java applications.

0
Share