Tuesday, April 30, 2019

Starting Spring Boot Application in Debug mode

Start the Spring boot application with the following jvm argument.

mvn spring-boot:run -Drun.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"

Saturday, April 20, 2019

Maven attach source code for external Jar

For Java project that uses Maven for dependency and building we can attach the third party library source. By default the source is not available, using the following commands we can down load the associated source and java doc from maven repository by reading the project pom file.

Maven will not be able to download sources and docs if those were not published for a particular library.


mvn dependency:sources
mvn dependency:resolve -Dclassifier=javadoc
//to download source for only one library
mvn dependency:sources -DincludeArtifactIds=spring-boot


Now after executing the above two commands, maven will download the respective sources and java docs. Now we can attach the source in the IDE. For eclipse specially it is better to use the Maven Eclipse plugin

mvn eclipse:eclipse -DdownloadSources=true
mvn eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=false

Executing the above commands will also download the sources and it also updates the .classpath file. Now refreshing the Project in side eclipse should be able to map the corresponding sources for the external jars.

Saturday, April 13, 2019

Failed to instantiate [java.util.List]: Specified class is an interface in HTTP controller handler?


Problem Use case:

Following SpringBoot Rest Controller is not able to map the request payload

@Controller
@RequestMapping("/api")
  public class BlogController {  
    @RequestMapping(value = "/blogstories", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
       public ResponseEntity<List<BlogStoryObject>> addUpdateblog(List<BlogStoryObject> blogItems) {
          List<BlogStoryObject> result = new ArrayList<BlogStoryObject>();
    //TODO:: Call Service to update/save objects
    return new ResponseEntity<List<RootBlogStoryObject>>(result, HttpStatus.OK);
 }
}


Exception Details [Truncated]:

And the error thrown at runtime is Failed to instantiate [java.util.List]: Specified class is an interface.

Solution

Solution to the problem is to @RequestBody annotation to the method definition, so the following will work.

public ResponseEntity<List<RootBlogStoryObject>> addUpdateblog(
  @RequestBody List<RootBlogStoryObject> blogItems) {
  /////implementation goes here

}

Friday, April 12, 2019

Spring Boot Error : Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory


Problem Use case:
While starting a Spring Boot Application using

mvn spring-boot:run

The Application fails to start
Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

Exception Details [Truncated]:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.9.RELEASE:run (default-cli) on project Javaexp-springboot-rest: An exception occurred while running. null: InvocationTargetException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean. -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Solution
Update pom.xml and use the spring-boot-starter-web

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <version>1.5.9.RELEASE</version>
</dependency>
Now do a new build and the application should be able to start.

Friday, April 5, 2019

Spring Boot CommandLineRunner

CommandLineRunner is an interface which allows us to write code that would be executed when the SpringBoot Application is initialized and before the startup is finished.

Technology used

  • Java 8
  • Spring boot 1.5.9
  • Logback 1.1.1.1
  • Maven 3.5.0

Implementation

This project uses Maven to build the project.  It shows a very simple example of a Spring boot Application and two Classes implementing CommandLineRunner.

High level steps as described bellow with sample code

Define the pom.xml file
Write Spring boot app class
Write Spring boot CommandLineRunner class
Change the order with Order annotation

For simplicity the pom file is not provided here, but it can be found on the git repo here https://github.com/siddharthagit/spring-boot-references/blob/master/spingboot-resttemplate/pom.xml

SpringBoot Application Class
ResttemplateApplication.java
@SpringBootApplication
public class ResttemplateApplication {

  private static final Logger log = LoggerFactory.getLogger(ResttemplateApplication.class);

  public static void main(String args[]) {
    log.info("about to call SpringApplication.run()");
    SpringApplication.run(ResttemplateApplication.class, args);
    log.info("completeed executing SpringApplication.run()");
  }

}
Next we will provide two Classes which implements CommandLineRunner interface.

LoadAllEndpoint loads all the available endpoints by calling  github's REST API
LoadAllEndpoint.java

@Component
@Order(1)
public class LoadAllEndpoint implements CommandLineRunner {

  private static final Logger log = LoggerFactory.getLogger(ResttemplateApplication.class);

  @Override
  public void run(String... args) throws Exception {
    log.info("about to call LoadGithubRepo.run()");
    RestTemplate restTemplate = new RestTemplateBuilder().build();
    ResponseEntity apis =
        restTemplate.getForEntity("https://api.github.com", JsonNode.class);
    
    //log.info(apis.toString());
  }
}
LoadGithubRepo returns all the available in github for an account by calling  github's REST API
LoadGithubRepo.java

@Component
@Order(2)
public class LoadGithubRepo implements CommandLineRunner {

  private static final Logger log = LoggerFactory.getLogger(ResttemplateApplication.class);

  @Override
  public void run(String... args) throws Exception {
    log.info("about to call LoadGithubRepo.run()");
    RestTemplate restTemplate = new RestTemplateBuilder().build();
    ResponseEntity repos = restTemplate
        .getForEntity("https://api.github.com/users/siddharthagit/repos", JsonNode.class);
    //log.info(repos.toString());
  }
}
Run the application

mvn spring-boot:run
Console Output (some part)

AnnotationMBeanExporter:431 - Registering beans for JMX exposure on startup
ResttemplateApplication:21 - about to call LoadAllEndpoint.run()
ResttemplateApplication:21 - about to call LoadGithubRepo.run()
ResttemplateApplication:57 - Started ResttemplateApplication in 2.07 seconds
ResttemplateApplication:17 - completed executing ResttemplateApplication.run()

Summary

CommandLineRunner is useful when we need to execute code before the Applicaton startup completes
We can have multiple implementations of CommandLineRunner
We can arrange the order of execution between different implementations using Order annotation

Download and Run

git clone https://github.com/siddharthagit/spring-boot-references.git
cd spingboot-resttemplate
mvn spring-boot:run

Tuesday, March 5, 2019

Spring boot with Thymeleaf example

This blog shows how to use Thymeleaf as a template engine with Spring boot.


Technologies Used

  • Java 8
  • Spring framework 1.5.9
  • Spring boot 1.5.9
  • Thymeleaf 2.1.6
  • Tomcat embed 8.5.23
  • Logback 1.1.1.1
  • Junit 4.12
  • Bootstrap 4
  • Maven 3.5.0

Implementation

This project uses Maven to build the project.  It shows a very simple example of a login page with corresponding Spring boot controller.
The goal of this project is to have a login page rendered using Thymeleaf template.
The template it self uses the bootstrap css for styling.

High level steps as described bellow with sample code

Define the pom.xml file
Write Spring boot app class
Write Spring boot controller class
Write  Thymeleaf Template for the controller class
Write the CSS referred by Template file

pom.xml



<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <artifactId>Javaexp.blogspot.com-thymeleaf</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>war</packaging>
  <name>Javaexp.blogspot.com Thymeleaf</name>
  <description>Javaexp Thymeleaf Example</description>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath />
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
  
    <!-- Springboot -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>1.5.9.RELEASE</version>
    </dependency>

    <!-- test -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

    <!-- for Thymeleaf -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- hot swapping, disable cache for template, enable live reload -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <optional>true</optional>
      <scope>runtime</scope>
    </dependency>

  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <addResources>true</addResources>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <configuration>
          <webResources>
            <resource>
              <directory>dist/</directory>
            </resource>
          </webResources>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>



StartWebApplication.java

package com.blogspot.blogger;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StartWebApplication {

  public static void main(String[] args) {
    SpringApplication.run(StartWebApplication.class, args);
  }

}



WebLoginController.java

package com.blogspot.blogger;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class WebLoginController {

  @GetMapping("/login")
  public String login(Model model) {
    return "login";
  }

}



For the Thymeleaf template file put it under src/main/resources/templates/login.html

login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"></meta>
<link rel="stylesheet" type="text/css" th:href="@{~/css/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" th:href="@{~/css/style.default.css}" />
<title>Javaexp.blogspot.com Thymeleaf Example</title>
</head>
<body>
  <div class="container">
    <div class="modal-dialog">
      <div class="loginmodal-container">
        <h1>Login to Your Account</h1>
        <form>
          <input type="text" name="user" placeholder="Username"></input> <input
            type="password" name="pass" placeholder="Password"></input> <input
            type="submit" name="login" class="login loginmodal-submit"
            value="Login"></input>
        </form>
        <div class="login-help">
          <a href="#">Register</a> - <a href="#">Forgot Password</a>
        </div>
      </div>
    </div>
  </div>
</body>
</html>


application.properties

#SPRING BOOT MVC
spring.mvc.view.prefix=/static/
spring.mvc.view.suffix=.html

Run the Spring boot Application

$ mvn spring-boot:run

INFO restartedMain o.a.c.h.Http11NioProtocol:179 - Starting 
ProtocolHandler ["http-nio-8080"]
INFO restartedMain o.a.t.u.n.NioSelectorPool:179 - Using a shared selector for servlet write/read
INFO restartedMain o.s.b.c.e.t.TomcatEmbeddedServletContainer:201 - Tomcat started on port(s): 8080 (http)
INFO restartedMain c.b.b.StartWebApplication:57 - Started StartWebApplication in 2.337 seconds (JVM running for 2.735)

Demo

Goto : http://localhost:8080/login



Download and Run

git clone https://github.com/siddharthagit/spring-boot-references.git
cd spingboot-web-thymeleaf
mvn spring-boot:run

Friday, March 1, 2019

Installing Couchdb on GCP Compute Engine

This article covers the steps that needed to install Apache Couchdb on Google Cloud Platform.

There are various way of how to achieve this, that is having a Compute Engine (VM) installed with Couchdb.

One option is to use the the Marketplace in GCP which offers quick option to deploy on Cloud Platform.
Login to GCP and click on the  Marketplace Icon and then search for CouchDB. Although we would still need to perform some additional steps like Creating Firewall Rule etc so that we can access the instance after getting VM with CouchDB installed from Marketplace.



Rather than using the Marketplace, we would do everything manually on the VM Instance.
Following are the steps in details that i had to take to lunch an instance of CouchDB, do configuration update and create Firewall Rules to allow access to the instance.

High level steps as covered bellow are

  • Create an Instance of Google Cloud Engine Instance
  • Install Apache CouchDB in the VM
  • Configure the Database Instance
  • Configure Firewall Access

Create Google Cloud compute Engine instance.


SSH to the VM Instance.

Before installing the Apache CouchDB we will install some useful software that we would need like nano editor.

sudo apt-get install nano

Install CouchDB

sudo apt update
sudo apt-get install apache2 couchdb

Check Status of CouchDB

Following commands are useful to check the status of CouchDB instance, start it and stop it etc.
sudo systemctl stop couchdb.service
sudo systemctl start couchdb.service
sudo systemctl enable couchdb.service
sudo systemctl status couchdb.service

Change the bind address of CouchDB

Normally the CouchDB listens to port 127.0.0.1 which is localhost.
When we deploy the CouchDB on VM on GCP we would like it to be accessed from outside the VM also, for that we need to modify the bind address. We do that by updating CouchDB configuration file
nano /etc/couchdb/default.ini
port = 5984
bind_address = 0.0.0.0

Add Firewall rule for the VM instance

We will now add a new Firewall rule to allow access to the VM on which we have CouchDB installed.
For that go to Navigation Menu -> VPC Networks -> Firewall Rule and click on 
Create Firewall rule

Add the necessary details like follows,


Now we we should be able to access the instance over internet

Access the Instance

Open a browser and go to external-ip:port/_util/, we should be able to see a page like as bellow