Spring Application Setup – Shop Smart

Project Setup

Following the previous article, one thing is very clear that our application will deal with users. The users can then be categorized into customers, sellers, operations, administrators and other. But at the core, all of them are users and they will need credentials to access the system.

Also, we talked about various modes of authentication, but let us assume that the basic mode of authentication is database or file. So, let us define the user tables as shown below:

SS_USER – The User Table

We will keep it simple for now with the following columns:

SS_USERPROFILE – The User Profile Table

This table contains the profile data for a user and it is linked to the user table with the foreign key USERID.

SS_ADDRESS – The Address Table

Why do we need a separate Address Table?
We need this because of the fact that an address can be shared among multiple people. It is worthless to repeat it for many such users in the User Table or the profile table.

Also, if we want to store multiple type of addresses for a person like office address, home address, billing address, holiday home address, then for each such address we just need to alter the SS_USERPROFILE table and add one column instead of ten columns.

Also, in case of an office address, the address for all the employees more or less remains same. The only thing which changes is the name & employee id of the employee. So, having a separate address table can help us in reusing the the office address for several hundred employees. If our “Shop Smart” venture becomes a hit and we have many corporate customers.

SS_PASSWORD – The passwords table

Now a days there are so many passwords to remember, we keep on changing and forgetting passwords every now and then. So, there are scenarios when we try to login to a website using older passwords, in that case the user must be reminded that the password has changed X days ago.

Many other good things can be done if we keep a track of these passwords. For e.g. Not allowing a recent password to be used again while changing passwords etc.

This definitely is not the perfect database setup, but for our application, let us start from here. Few important points worth clarification:

  • We will store all date and time in UTC Time Zone.
  • We will store a Time Zone for each user.
  • While displaying the dates on the UI, we will convert the date and time into user’s time zone.

Some Important Decisions

We need to make these decisions in the beginning so that we can follow the same standards all the way till the end. These are not hard and fast rules but are important for a maintainable application, and we know that maintainability is an important non-functional requirement.

Layered Architecture

We are developing a layered application, which will have a minimum of three layers as mentioned below:

  • The Web Layer – mostly deals with the request/response from and to the user. Can also perform session management and other web related work.
  • The Business Layer – the layer is invoked by the web layer and can be used to complete all business requirements by interacting with various databases, rest/soap weebservices, payment gateways etc.
  • The DataAccess Layer – it contains the interaction with the real databases and various data sources, manages the cache etc.
Annotation Driven Programming

We will primarily use annotations from Spring, Hibernate, AspectJ and other frameworks. There is no specific reason for that, but somewhere I feel that the XMLs are the technology of the past and Annotations keeps the code far more cleaner to maintain. Also, it is good not to be bothered about half a dozen XML configurations if that can be done in a Java configuration.

Exception Handling
  • All the exceptions must be propagated until the outer layer of the application, where we can have some context based logging. Every layer can add its details to the exception but no one should log it except for the layer which knows the context. This is precisely for avoiding unnecessary and duplicate logging of exceptions.
  • Appropriate Exceptions must be defined for different purposes. For e.e. AuthenticationException, AuthorizationException, ResourceNotFoundExcepetion, ServiceNotAvailableException .
Logging
  • Each log must be printed with a unique ID, so that it can be traced back with the ID.
  • Each log must be logged with appropriate levels and must not convey false alarms. For e.g. not everything is FATAL or ERROR or INFO.
  • Do comprehensive logging, because in production environment which might have INFO level logging turned on, it would be tough to debug issues if the log is not complete.
  • Entry and Exit logs should be there for each public method in TRACE level.
  • Success operations must be logged in INFO level.
  • Incorrect code paths and unexpected inputs must be logged in WARN level.
  • Exceptions must be logged with ERROR level, if they stop the functionality from proceeding and halts the request.
  • Exceptions must be logged with WARN level, if they do not hamper the functionality and operations can proceed further.
  • Exceptions must be logged with FATAL level, if they can harm/crash the application
  • Unit Testing

    We will have a full Unit Test coverage (another non-functional requirement) for a better test-ability of the application. We will mostly follow a test driven development and write test cases before writing the code. Let us integrate JUnit as well.

    We will use the HSQL (Hyper SQL) database, which is an in memory database, only for testing purpose.

    The Basic Structure – Spring Application Setup

    We will start with a jar named common.jar and the responsibility of the jar is to act as a single point of contact for all the database calls.

    Why a common jar?

    There can be many common features which needs to be accessed in the same way from every module of the application. This can promote re-usability as well, also the common configurations can be placed in this jar like aspects, some part of security configurations and many more. It makes a lot of sense to have few such common pieces of code.

    The below image is the current structure of the project.
    Spring Application Setup

    Explaining the above project structure

    The project contains the following directories:

    • src – All source code, which can be built and deployed on production servers is stored in the src directory.
    • test – All test code, which is used for unit testing can bee stored in this directory.
    • resource – All resources, likes .properties, .sql, some images which are common to the complete applciation and some xmls(if needed) will be stored here.
    • test-resource – The counter part of the resources folder for the test setup.
    • lib – the directory which contains all the jars used in the application.
    • testlib – the directory contains all the jars which are only needed by the test classes written in the application. Like junit.jar, hsqldb.jar and few other jars used for mocking purposes.

    If you are using eclipse for practicing, I would recommend you to create two User Libraries one with the name APP_LIB whose classpath contains all the jars in the lib directory. Another with the name TEST_LIB whose classpath contains all the jars in the testlib directory.

    This is a good practice, because if a new jar is to be added and used in a set of projects then you just need to add it to the User library and it will be propagated to all other projects where the User library is in the classpath.

    If you choose not to follow this, then if you have to add any new jar into all the projects then you must add it to each ones classpath without fail.

    That would be all about the basic Spring Application Setup.

    Walking through the code

    Once the directories are in place with all the jars, then we need to start adding source code. As I mentioned we will be following a Test Driven Development approach, we will be writing the test first.

    For simplicity, I already added the table creation scripts (init.sql and init-test.sql) on github. I made two copies of it, one in the resources directory and other in the test-resources directory.

    These two .sql files are not exact replicas, because HSQL won’t fully understand the MYSQL dialect. Hence, I made necessary changes to the init-test.sql for supporting HSQL Dialect.

    Building the data source and running the init-test.sql

    Whenever we run our test cases, we would prefer that the in-memory db (HSQL) is built and it supplies the data source to our application.

    When the actual integration testing or production application runs, the data source will use the init.sql file and run it on a running MySQL instance.

    Configuration Classes for the Spring Application Setup

    JndiConfig

    @Configuration – Notice the @Configuration annotation on this class, it tells Spring that this is a configuration class, which is equivalent to an XML configuration in the older version of Spring.
    @Profile – Notice the @Profile annotation on this class, which takes a value “dev”. This means that a Spring bean will only be created from this class when the application is run in development mode. “dev” is not a keyword, you can choose anything you want.

    Inside this class we can create as many beans as we want. Let us create the Datasource bean, and name it “dataSource”. Once the bean is built and initialized, then we can use it anywhere in the application. The method public DataSource dataSource() throws Exception creates an embedded database of HSQL type and executes the script init-test.sql located in the classpath of the project.

    HibernateConfig

    @EnableTransactionManagement – This annotation tells Spring to enable Transaction Management in the application. We need this because all the database operations are transactional in nature.

    @ComponentScan – This tells the Spring container to scan through all the packages supplied to the annotation and register and instantiate any bean which is yet not registered/instantiated. An exclude filter is present in the configuration and it stops Spring from scanning and registering the classes which are marked as configuration classes. This is done to make the bean registration process faster, because if the same configuration file is registered at one place there is no need to re-register it or just even look through it and waste CPU cycles.

    Apart from the above four annotations we also have the following:

    @Value – This annotation reads the value of the property name supplied to the annotation and populates it to the variable following it. In current scenario the variable hibernateDialect will be populated with org.hibernate.dialect.MySQLDialect value, which is present in the test properties file.

    @Autowired – This annotation basically injects a bean into this class. The name of the bean to bee autowired is supplied immediately after the annotation. Here, the dataSource bean is injected and populated in the instance variable DataSource dataSource;

    Apart from this we also create three beans

    • sessionFactory – Which is the session factory for hibernate. This can be a pool for sessions and we can fetch one from the factory when needed.
    • transactionManager – This bean enables transaction management of the application. The transaction manager requires the seession factory as well.
    • Note – Point worth noting is that this class is not in the test source directory but in the src directory. This is alright because there is no specific configuration for test. The only test specific configuration is for the dataSource which is defined in the JndiConfig configuration in the test. As it is obvious that the test database and production database must be different.

      Later we will discuss all the aspects of the hibernate configuration in a separate post dedicated only for hibernate.

      TestConfig

      This class is another configuration class which is needed only for setting up the test related setup.

      Following annotations are also used in this class:
      @PropertySource – This annotation contains the source of all the properties being used in the application. Here, as it is a “dev” profile configuration, we are using the shopsmart-test.properties file, which is expected to be present in the classpath.

      @ComponentScan – This tells the Spring container to scan through all the packages supplied to the annotation and register and instantiate any bean which is yet not registered/instantiated.

      It also creates a bean appProperty, which is a property container or configurer. This populates variables with property values from the properties file mentioned in the @PropertySource.

      AppContextTest

      This is the first class till now, which actually works. This is the JUnit Test class, all the methods inside this class will be run as separate tests.

      Here is a list of annotations which are used in this class:
      @RunWith – This annotation tells JUnit to run this test class with Spring JUnit’s class runner. More on this in a different post.
      @ContextConfiguration – It tells Spring which configuration file to pick up for building spring context. We already created the TestConfig class, so we can use it for building the Spring context.
      @ActiveProfiles – This annotation sets one or multiple profiles as the current set of profile under which the application is running, the name is not a keyword, you can use any identifier and all the classes with this identifier will be registered as Spring beans. For testing we will name the profile as “dev”.
      @Transactional – This annotation ensures that each of the method in class will be run under a transaction.
      @BeforeClass – This annotation is put over a method in the Test class and will be run once for this class. It sets up the one time configuration for testing. Here, we just configure the log4j logger. (we are temporarily using log4j logger, our goal is to use slfj logger)
      @Test – This marks a method as a valid runnable test.

      Testing

      Now we are partially done with Spring Application Setup, let us write a test method and check if our spring context was properly built. A good test would be to see if the dataSource bean is present. A not null check will do.

      We already injected the dataSource bean in the test class, now we can check an assertion for being not null. Hence the below method:

      Conclusion

      This is a long post and we learnt many things here.

      • We learnt Spring Configuration and meaning of all the annotations there.
      • We learnt how to integrate JUnit in the application.
      • We learnt about configuring in memory HSQL DB.
      • We learnt about Hibernate basic configuration.
      • And we also learnt about Spring profiles in brief

      I hope it helped you in learning basic project setup and Unit testing it. Please leave comment, in case I am not clear at any point. Also the code is completely shared on Github and can be downloaded and used as is.

      Github

      Here is the link for Shop Smart Github repository

      Don’t forget to subscribe to TechieMe to get updates on latest posts.

    • jammy

      post more in this series.