Author Archives: yogesh.mali@gmail.com

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

 

 

How to resolve PKIX Path Building Failed in Docker Container

Consider the following scenario in which a docker container was throwing SSLHandshakeException. You are running a service in a docker container. This service calls another service in another docker container and the API calls fails with following error:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target

In this post, I will show how to resolve SSLHandshakeException within docker container with a simple fix.

Previously, I showed how to run your services using docker container in this post.

This scenario is very common with microservices running in docker containers. Also there are few ways you can resolve this issue, but I will suggest a standard way to resolve this issue.

Standard solution is to get SSL certificate of target service and import that certificate in keystore of Java runtime that calling service is using.

Docker Container Logo

How do we resolve Docker Container – SSLHandshakeException?

The dilemma exists because every time you stop docker container and restart or kill a docker container and restart it, it will change container id. With that, you can’t be sure where JAVA_HOME of your calling service exists.

So depending on what Java environment are you using for your docker container, the easiest thing you can do is copy a cacerts keystore file from your local host machine to docker container when building the docker image.

Before you copy cacerts, make sure you import the SSL certificate of the target service. You can use keytool command to import this certificate.

Now add a below command in your Dockerfile

COPY ./cacerts /usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/lib/security/cacerts

This will build your docker image and will resolve the PKIX Path Building Failed error.

Drawback

A drawback of this solution is that you have to make sure that your base docker image has jvm path mentioned in the command. If it is different from above, you will have to first find that. Also if you call multiple services, you will have to get SSL certificates of all those servies.

One important thing to note that this should not happen in your production environment, but mostly development sandbox. Production environment should have CA signed SSL certificates on load balancer and all your services should be behind that load balancer while sharing the same certificate.

References

  1. Docker Containers – docker

RentersFeedback.com is Rentersvoices.com

Yes, yes, Rentersfeedback.com is Rentersvoices.com. Previously I described how I came up with an idea to create an application here. I am rebranding RentersFeedback to RentersVoices. I was actually looking for that domain for some time now, finally, when I was able to get the domain, I immediately made the shift.

Why Rebranding?

You can argue that rebranding RentersFeedback to RentersVoices seems unnecessary, but I always had a hint that I needed this domain. Even when I was launching Rentersfeedback.com, I was looking for the domain rentersvoices.com and I never got it. It was taken.

  1. Renters Voices is a better name. Renters Feedback sounds very forced name.
  2. Now I can implement a few more ideas that I have in mind based on rentersvoices name.
  3. I also received good feedback from Indiehackers.com here.

Domain names are not easily available. Sometimes, it takes a lot of time to constantly look for a domain that you want. When I started building an application, I looked for rentervoices.com, but it wasn’t available. Now when I got the right domain, it was no no-brainer to rebrand my application to rentersvoices.com.

Domain Change To RentersVoices

Marketing

At Indie Hackers meetup, I got a few marketing ideas from experienced indie hackers. Especially I really liked the idea to use flyers and talk to people at university campuses and ask them to post reviews.

I hope the rebranding will help me take that risk with marketing and get more leverage to push forward.

A few other ways to market the application are

  • To join some of the Facebook groups where they post about rental properties. Ask the people to submit reviews
  • Reddit communities can be equally helpful to get some feedback.
  • Talk to renters and people. Talking to people is the oldest form of marketing.

So sign up at rentersvoices.com and post a review about your rental apartment or house.

 

 

How to integrate reCaptcha with Spring Boot Application

In this post, I want to show how to integrate ReCaptcha in a Spring Boot application. This will be an important step if you have forms in your application and if those forms are publicly available on the internet. You can face a lot of spams or bots trying to fill those forms. To avoid these spams from bots, ReCaptcha is of utmost importance.

Google offers a reCaptcha service that we will integrate with Spring Boot application to stop bots from submitting the forms in our application.

Registration with Google for ReCaptcha

Google offers a reCaptcha service that developers can use in their applications. As part of this implementation, we will register our service in Google APIs so that Google can provide us credentials to use while calling its service.

We can register our site at Google Recaptcha Administration. This registration will provide us with site-key and site-secret.

Now as part of Spring boot application, we can store these credentials in application.properties file as below:

# ====================================================================================
# Google reCaptcha Settings
# ====================================================================================
google.recaptcha.key.site=site-key
google.recaptcha.key.secret=site-secret

We will make these properties available through a spring bean object in our application, so we can use them when we call Google Recaptcha Service.

UI changes to display ReCaptcha box

Now to display Recaptcha box on your form, we will add the following code in our templates where our public form resides. In this case, I am putting Recaptcha box in Contact Us and Sign Up pages as those are publicly available forms.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>Renters Feedback</title>

    <!-- other scripts and stylesheets -->
    <script src='https://www.google.com/recaptcha/api.js'></script>

</head>
<body>

<form method = "post" id="contactus" th:action="@{/contact}">
<!--- other code to display contact us form -->
<div class="g-recaptcha" th:attr="data-sitekey=${@captchaSettings.getSite()}"></div><br/><br/>
<span id="captchaError" class="alert alert-danger col-sm-4" style="display:none"></span>
</form>

</body>
</html>

 

Server-side handling of ReCaptcha

So as we have a widget on our form. When a user completes a challenge and submits the form, the request will be sent to the server containing an encoded site key and a unique string that identifies user’s challenge completion.

But on the server side, we can’t just assume and trust what the user has submitted. So we need to verify this captcha challenge by sending a request to Google API at https://www.google.com/recaptcha/api/siteverify by passing captcha response we have received.

If the verification is successful, the json response from API will contain a success parameter.

If the verification fails, then an application will throw an exception and reCaptcha library will instruct a client to create a new challenge.

One thing to understand here is that we limit how many attempts a client can make to reCaptcha challenge. The reason for this is to avoid any kind of DoS attack. Of course, this is precautionary and elementary step. We implement ReCaptchaAttemptService to block if a client tries to use the challenge for more than 4 attempts.

Demo of the complete workflow of ReCaptcha

Conclusion

In this post, we showed how we can use google reCaptcha service to integrate a reCaptcha widget in a form that is publicly available to avoid bots spams. From the security perspective, this is an important step and developers should take into account this important feature for their web applications.

References

  1. Recaptcha with Spring Boot Application – Recaptcha With Spring Boot Application
  2. Protecting Spring Boot application with Google Recaptcha – Protecting Spring Boot Application