Category Archives: Java

Error with Spring Context Lookup Failed

In this post, I will show how to resolve the error Spring context lookup failed. This scenario resembles if you are using Spring Boot 2.x or Spring Boot 1.5. I was recently using Spring Boot 2.x and ran into an error like below:

org.glassfish.jersey.server.spring.SpringComponentProvider: Spring context lookup failed, 
skipping spring component provider initialization.

 

Why did I see this error?

Before I can explain why I saw this error. Let’s sort of some basic concepts about what  ContextLoaderListner is and what DispatcherServlet is.

Spring boot creates multiple contexts. It will start with a root context and the rest of the contexts will be child contexts. Child contexts can access the beans defined in the root context, but not vice versa.

ContextLoaderListener

When you start the Spring Boot application, ContextLoaderListener creates the root application context. Spring boot will share this root context with all other child contexts that DispatcherServlet will create. Usually, you define ContextLoaderListener in web.xml like below:


<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
  
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>

ServletContext stores this root application context and one can use WebApplicationContextUtils to retrieve this context.

DispatcherServlet

DispatcherServlet is a HttpServlet whose primary purpose is to handle incoming web requests matching the configured URL pattern. When you define DispatcherServlet in Spring configuration, Spring will use a configured configuration file or creates its own configuration file based on controllers and views in the code.

DispatcherServlet creates one child application context per servlet entry.

Why Spring Context Lookup Failed:

Spring Boot 2.x offers a programmatic way to configure your contexts and servlets. In my particular case, I was using this programmatic way. But I had configured anyway to load application context, especially root application context.

To configure this root application context, I needed ContextLoaderListener . Since I didn’t want to use web.xml , I looked for a programmatic way. Spring boot 2.x offers this through SpringBootServletInitializer . Basically, when we extend the root application class with SpringBootServletInitializer, it binds Servlet, Filter, and ServletInitializer beans from the application context to the server. This also allows us to create a WAR archive of our application and run in any web container.

Once I added SpringBootServletInitializer in my main Spring Boot Application class, I was able to resolve this error. The code for that will look like below:


@SpringBootApplication
public class Application extends SpringBootServletInitializer 
{    
    public static void main(String[] args) 
    {
        SpringApplication sa = new SpringApplication(Application.class);
        sa.run(args);
    }
}

 

Conclusion

In this post, we showed how we can resolve an error Spring Context Lookup Failed. If you have any feedback about this post, please comment and I will be happy to answer.

References

  1. ContextLoaderListener vs DispatcherServlet
  2. Spring Boot Servlet Initializer
  3. Upgrade Spring Boot and adding Spring Boot Actuator – Spring Boot Actuator

 

 

RentersFeedback.com

RentersFeedback is a brainchild from a tweet that a friend tweeted back in August:

Tweet from a renter

Based on this tweet, I thought it would be nice if renters have some say about landlords. Around the same time, my girlfriend was looking for an apartment/house to rent. Even though we found a place, we were not sure if it’s a good place. And there were no reviews about this place. On the first impression, the house didn’t look like a place where anybody has lived in a long time, but we made our decision and went ahead with it. It would have been nice if there was a review of this place.

I am sure when most people are looking for places to rent, they use services like Padmapper or Zillow which offers the easiest way to find places based on area, requirements, budget, other facilities. But none of these applications offer a review system.

What this will solve?

Renters Feedback will solve the much-needed place to provide reviews about the places that people are renting. This will help future renters to look for good places to rent. This will also make landlords and rental management companies more accountable. I hope Renters Feedback can help renters with reviews for the places they want to rent.

What about Yelp?

Yelp.com has been providing reviews of restaurants, small businesses, and other things, but rarely of a standalone house to be rented or a rental management company. Yelp has done a tremendous job, but it lacks in this one area.

Why an application with a single functionality?

Less is more. Simple functionality matters in long terms than a complicated one. In marketing, there is a term affordance that refers to the perceived and actual properties of the thing, primarily those fundamental properties that determine how the thing could be used. A single functionality of the application will help users to navigate and use the application efficiently.

Techstack

To build RentersFeedback.com, I have used Spring Boot Microservice based architecture. I have implemented the current user interface using Twitter Bootstrap, CSS, Javascript, Google Javascript API, and Thymeleaf. Backend is written using Java and database supported.

Using Redis for caching, Google for OAuth2 authentication along with regular authentication.

Heroku.com is my choice of the cloud platform to launch the application. It offers an easy way to assemble all the needed services like database, Redis, and the server itself.

One future change for this might be to move the user interface to reactjs. Something that is currently I am working on.

Feedback

I would love it if you could use the application and would appreciate any feedback.  Subscribe to my blog to find out more about renters’ feedback.

 

Deploying Spring Boot Application to Heroku

Heroku is a platform as a service (PAAS) that helps developers to build, deploy, and run applications on a cloud platform. Deploying Spring Boot application to Heroku is a straight forward process. I will describe this process in this post. There are actually multiple ways to deploy a spring boot application. The simplest way to deploy the application is to use maven built jar file and run that jar file on Heroku server.

In my previous post, I showed how to use Spring session in your Spring Boot application.

Before I show one of these two methods to deploy the application, we assume that you have created an account on Heroku.com, if not first please create an account and download Heroku-CLI (Command Line Interface). I also assume that you have git downloaded and installed.

Initial Deployment with Heroku

Once you have Heroku account and Command Line Interface downloaded, let’s start deploying the Spring Boot app with repository.

Create an application directory on your development environment.


git init
git add .
git commit -m "first commit"

Now you can either create an app in Heroku through web-interface OR through Heroku CLI.

heroku create rentersfeedback would create the application in Heroku.

As part of this post, I am deploying an alpha version of my application rentersfeedback.com

Once you add the source code to the directory, we can push the repository to heroku.  Every time you push the repository to Heroku, Heroku’s builder will build the application and launch it.

git push heroku master

Despite this initial push, we don’t have the application ready to use yet.

Database Configuration

For this application, I will be using Postgres database. Heroku offers a couple of ways to add database as an add-on.

Once Postgres database is added, go to settings -> view credentials  this will provide us database credentials.

Now we can access the database server through pgAdmin Postgres Administration and create database and database tables for our application.

Back in Heroku web-interface, if you go to the application settings page, click on reveal Config Vars and set up the following variables


SPRING_DATASOURCE_URL= 
SPRING_DATASOURCE_USERNAME= 
SPRING_DATASOURCE_PASSWORD= 
SPRING_DATASOURCE_DRIVER-CLASS-NAME=org.postgresql.Driver 
SPRING_DATASOURCE_TYPE=org.apache.tomcat.jdbc.pool.DataSource 
SPRING_JPA_DATABASE-PLATFORM=org.hibernate.dialect.PostgreSQLDialect

As you can see that we are using datasource type as tomcat jdbc pool and not the standard hikariCP which Spring boot provides. To make sure to work this, we have to add a dependency of tomcat-jdbc as follows:


compile('org.apache.tomcat:tomcat-jdbc:9.0.29') 
compile('org.postgresql:postgresql:42.2.8')

If you don’t specify data source type as tomcat-jdbc, Heroku throws an error for Postgres database as below:

Caused by: java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl

This will get our Spring Boot app to work with the Postgres database while deploying on Heroku.

Configuration of Gradle to build a jar file

So by default, Heroku supports maven. If you want to use Gradle to build your application, you can use the following guidelines.

Now if you push these changes to heroku and build the application, the application will throw the following error while starting up



2019-11-30T17:05:46.096985+00:00 heroku[api]: Deploy 291326d by xxx@gmail.com 
2019-11-30T17:05:46.097021+00:00 heroku[api]: Release v9 created by xxx@gmail.com 
2019-11-30T17:05:46.378258+00:00 heroku[slug-compiler]: Slug compilation started 
2019-11-30T17:05:46.378269+00:00 heroku[slug-compiler]: Slug compilation finished 
2019-11-30T17:05:46.755655+00:00 heroku[web.1]: State changed from crashed to starting 
2019-11-30T17:05:53.121398+00:00 heroku[web.1]: Starting process with command `java -Dserver.port=5000 -jar build/libs/myapp.jar` 
2019-11-30T17:05:54.260741+00:00 app[web.1]: Error: Unable to access jarfile build/libs/myapp.jar 
2019-11-30T17:05:54.784064+00:00 heroku[web.1]: State changed from starting to crashed 
2019-11-30T17:05:54.773714+00:00 heroku[web.1]: Process exited with status 1

To resolve this issue, I will add a task in my gradle script that will build a jar file when I deploy the application.


apply plugin: 'java' 

task stage(type: Copy, dependsOn: [clean, build]) { 
    from jar.archivePath into project.rootDir rename { 'app.jar' } 
} 

stage.mustRunAfter(clean) 

clean.doLast { 
   project.file('app.jar').delete() 
}

Setting up application.properties

We have deployed our application, configured database, and build script. Usually when spring boot application starts, it will access all the required variables from application.properties. So I will set up that file as follows:



# ==================================================================================== 
# = DATASOURCE 
# ==================================================================================== 
spring.datasource.url=${SPRING_DATASOURCE_URL} 
spring.datasource.username = ${SPRING_DATASOURCE_USERNAME} 
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD} 
spring.datasource.driver-class-name=${SPRING_DATASOURCE_DRIVER-CLASS-NAME} 
spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect = ${SPRING_JPA_DATABASE-PLATFORM} 
spring.datasource.type=${SPRING_DATASOURCE_TYPE} 
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true 
# ==================================================================================== 
# = Server SSL 
# ==================================================================================== 
server.port = 7443 
security.require-ssl=true

Setting up a custom domain

Heroku offers an easy option with SSL, so if you choose that, it is a straightforward approach with Let’s Encrypt to automatically manage the SSL certificate.

Now to set up the custom domain, add your domain and heroku will provide the target DNS server. For your corresponding domain provider, you will add DNS setting for CNAME(for www) and ANAME (root domain). Wait for a few hours for this setting to take place.

Access the application

We are ready to access the application now. Once you have pushed all the required changes to Heroku repository, heroku will build the application and launch it.

Now if we access rentersfeedback.com, we will be able to see the application as follows:

Renters Feedback

References

  1. Deploying Spring boot application to Heroku – deploy spring boot app
  2. Deploying Gradle application to Heroku – Gradle applications to Heroku
  3. Custom domains in Heroku – Custom domains in Heroku

 

 

Session Management with Spring-Session and JDBC

User session management is vital to keep user state in an application. The session helps to keep track of where the user is currently and if he comes back to check the application, it can be retrieved in a similar state. In this post, I will show how to use the Spring session with the database to maintain session data.

Spring Session

Spring session offers APIs to manage user sessions. This gives the flexibility to build an enterprise-level application using Spring Boot and still segregating with Spring Session. Another advantage of using Spring session is that it offers different storage options. You can store the session data in redis, database using JDBC or in-memory. Since we are able to store the session data in database, session data is not lost if application shuts down or crashes. This helps to manage user session iteratively.

In this post, I will show how I have used Spring session in my application Renters Feedback.

Create a Spring Boot based application

I will not be showing how to create a spring boot based application. The assumption is you know the basics of Spring Boot. Once you create a maven-based or Gradle-based Spring boot application, you can include a dependency for Spring session.

org.springframework.session:spring-session-jdbc:2.1.6.RELEASE

Configure Storage Type

With the Spring session, you have multiple options to configure the storage type. For this post, I will be showing how to use a database with JDBC to store user session data. With setting application.properties you can create required session tables on the fly OR you can create them before starting your application, so you don’t have to create them always.

From a production system perspective, I prefer to create tables while setting up an application once and never worry about it.

So before we can use the spring session, create the required database tables in your choice of database. In this post, I will be using mysql for database.

Create the following two database tables in your application database

create table SPRING_SESSION (
primary_id CHAR(36) NOT NULL,
session_id CHAR(36) NOT NULL,
creation_time BIGINT NOT NULL,
last_access_time BIGINT NOT NULL,
max_inactive_interval INT NOT NULL,
expiry_time BIGINT NOT NULL,
principal_name VARCHAR(100),
CONSTRAINT spring_session_pk PRIMARY KEY (primary_id)
);

create table SPRING_SESSION_ATTRIBUTES (
session_primary_id CHAR(36) NOT NULL,
attribute_name VARCHAR(200) NOT NULL,
attribute_bytes BLOB NOT NULL,
CONSTRAINT spring_session_attributes_pk PRIMARY KEY (session_primary_id, attribute_name),
CONSTRAINT spring_session_attributes_fk FOREIGN KEY (session_primary_id) REFERENCES SPRING_SESSION(primary_id) ON DELETE CASCADE
);

 

Configuring your application.properties  as follows:

spring.datasource.url=jdbc:mysql://127.0.0.1/sampledb?autoReconnect=true&useSSL=true
spring.datasource.username = sa
spring.datasource.password=*********
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.session.store-type=jdbc
spring.session.jdbc.initialize-schema=never
spring.session.jdbc.table-name=spring_session

One reason we specified spring.session.jdbc.initialize-schema=never is because we are manually creating the database tables.

Now to use Spring session in our application, we will configure Spring security and enable @EnableWebSecurity . Basically this will allow us to have a form-based authentication and on authentication, we can have a valid session created and stored in the database for logged in user.

I will not be showing how to enable Spring Security, you can read my old post about Using Spring Security in Spring Boot application.

Configuring JDBC HTTP Session

One key thing to do as part of this implementation is to enable Spring Session in the application by using annotation @EnableJdbcHttpSession as shown below:

@SpringBootApplication
@EnableJdbcHttpSession
public class HomeApplication extends SpringBootServletInitializer
{
	public static void main(String[] args)
	{
		SpringApplication.run(HomeApplication.class, args);
	}

}

As per Spring documentation here Spring Session, the annotation @EnableJdbcHttpSesion adds a bean with the name of springSessionRepositoryFilter . This filter handles replacing HTTP session implementation with Spring Session.

Running the application

Now to see the entire application, we can see the following recording to see how spring boot based application creates the session and stores in the database.

In conclusion, we showed how to implement session management using the Spring Session.

References

  1. Spring Session – Spring Session
  2. Spring Session with JDBC – Spring Session with JDBC