How to start with spring mvc and install dependencies - java

I am new to spring needed to know how to start and how to import dependencies in spring mvc. i am starting a project for web application possible with single page application

Best possible website to start is https://start.spring.io/ . On this select dependency package you need and get a kick start for your project. You can also install some dependency later as per your need in pom.xml file.

To start from scratch, move on to Build with Gradle.
If you know basics and want code template, do the following:
Download and unzip the source repository or clone it using Git: git clone https://github.com/spring-guides/gs-serving-web-content.git
cd into gs-serving-web-content/initial
Jump ahead to Create a web controller.
When you’re finished, you can check your results against the code in gs-serving-web-content/complete.
Build with Gradle
First you set up a basic build script. You can use any build system you like when building apps with Spring, but the code you need to work with Gradle is included here.
Create the directory structure
In a project directory of your choosing, create the following subdirectory structure; for example, with mkdir -p src/main/java/hello on *nix systems:
└── src
└── main
└── java
└── hello
Create a Gradle build file
Below is the initial Gradle build file.
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
jar {
baseName = 'gs-serving-web-content'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-devtools")
testCompile("junit:junit")
}
The Spring Boot gradle plugin provides many convenient features:
It collects all the jars on the classpath and builds a single, runnable "über-jar", which makes it more convenient to execute and transport your service.
It searches for the public static void main() method to flag as a runnable class.
It provides a built-in dependency resolver that sets the version number to match Spring Boot dependencies. You can override any version you wish, but it will default to Boot’s chosen set of versions.
**Create a web controller**
In Spring’s approach to building web sites, HTTP requests are handled by a controller. You can easily identify these requests by the #Controller annotation. In the following example, the GreetingController handles GET requests for /greeting by returning the name of a View, in this case, "greeting". A View is responsible for rendering the HTML content:
src/main/java/hello/GreetingController.java
package hello;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class GreetingController {
#RequestMapping("/greeting")
public String greeting(#RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
}
This controller is concise and simple, but there’s plenty going on. Let’s break it down step by step.
The #RequestMapping annotation ensures that HTTP requests to /greeting are mapped to the greeting() method.
The above example does not specify GET vs. PUT, POST, and so forth, because #RequestMapping maps all HTTP operations by default. Use #RequestMapping(method=GET) to narrow this mapping.
#RequestParam binds the value of the query String parameter name into the name parameter of the greeting() method. This query String parameter is not required; if it is absent in the request, the defaultValue of "World" is used. The value of the name parameter is added to a Model object, ultimately making it accessible to the view template.
The implementation of the method body relies on a view technology, in this case Thymeleaf, to perform server-side rendering of the HTML. Thymeleaf parses the greeting.html template below and evaluates the th:text expression to render the value of the ${name} parameter that was set in the controller.
src/main/resources/templates/greeting.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Hello, ' + ${name} + '!'" />
</body>
</html>
Developing web apps
A common feature of developing web apps is coding a change, restarting your app, and refreshing the browser to view the change. This entire process can eat up a lot of time. To speed up the cycle of things, Spring Boot comes with a handy module known as spring-boot-devtools.
Enable hot swapping
Switches template engines to disable caching
Enables LiveReload to refresh browser automatically
Other reasonable defaults based on development instead of production
Make the application executable
Although it is possible to package this service as a traditional WAR file for deployment to an external application server, the simpler approach demonstrated below creates a standalone application. You package everything in a single, executable JAR file, driven by a good old Java main() method. Along the way, you use Spring’s support for embedding the Tomcat servlet container as the HTTP runtime, instead of deploying to an external instance.
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#SpringBootApplication is a convenience annotation that adds all of the following:
#Configuration tags the class as a source of bean definitions for the application context.
#EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
Normally you would add #EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
#ComponentScan tells Spring to look for other components, configurations, and services in the the hello package, allowing it to find the controllers.
The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.
Build an executable JAR
You can run the application from the command line with Gradle or Maven. Or you can build a single executable JAR file that contains all the necessary dependencies, classes, and resources, and run that. This makes it easy to ship, version, and deploy the service as an application throughout the development lifecycle, across different environments, and so forth.
If you are using Gradle, you can run the application using ./gradlew bootRun. Or you can build the JAR file using ./gradlew build. Then you can run the JAR file:
java -jar build/libs/gs-serving-web-content-0.1.0.jar
If you are using Maven, you can run the application using ./mvnw spring-boot:run. Or you can build the JAR file with ./mvnw clean package. Then you can run the JAR file:
java -jar target/gs-serving-web-content-0.1.0.jar
The procedure above will create a runnable JAR. You can also opt to build a classic WAR file instead.
Logging output is displayed. The app should be up and running within a few seconds.
Test the App
Now that the web site is running, visit http://localhost:8080/greeting, where you see:
"Hello, World!"
Provide a name query string parameter with http://localhost:8080/greeting?name=User. Notice how the message changes from "Hello, World!" to "Hello, User!":
"Hello, User!"
This change demonstrates that the #RequestParam arrangement in GreetingController is working as expected. The name parameter has been given a default value of "World", but can always be explicitly overridden through the query string.
Add a Home Page
Static resources, like HTML or JavaScript or CSS, can easily be served from your Spring Boot application just be dropping them into the right place in the source code. By default Spring Boot serves static content from resources in the classpath at "/static" (or "/public"). The index.html resource is special because it is used as a "welcome page" if it exists, which means it will be served up as the root resource, i.e. at http://localhost:8080/ in our example. So create this file:
src/main/resources/static/index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p>Get your greeting here</p>
</body>
</html>
and when you restart the app you will see the HTML at http://localhost:8080/.

how to import dependencies in spring mvc?
Spring MVC or not, to manage dependencies you can use any of the Java packaging tools like Gradle or Maven (there are other option too , like ivy or ANT from ancient world :) )
How to start
https://start.spring.io/ Start any of the spring project from this website, select the dependencies you want. When you click on generate it will download a zip file which contains a project (gradle or maven) with all the dependencies you selected. And then, later you can add or change dependencies by editing your build.gradle (if you have selected gradle) or pom.xml (if you have selected maven).

Related

Hot Reloading Thymeleaf Templates and Resource Bundles in Spring Boot 2.1

I created a Spring Boot 2.1.3 application with i18n enabled, added devtools, and installed the Firefox LiveReload extension. Unfortunately, when I change my Thymeleaf templates or i18n messages, it doesn't change. The Spring Boot documentation seems to suggest all you need to do is install devtools, and it'll disable caching of static resources.
Here's what I did to create my app:
mkdir bootiful-i18n
cd bootiful-i18n
http https://start.spring.io/starter.zip dependencies==web,thymeleaf -d | tar xvz
Then I created a HomeController.java:
package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class HomeController {
#GetMapping("/")
String home() {
return "home";
}
}
I created a Thymeleaf template at src/main/resources/templates/home.html:
<html xmlns:th="http://www.thymeleaf.org">
<body>
<h1 th:text="#{title}"></h1>
<p th:text="#{message}"></p>
</body>
</html>
I added a messages.properties file in src/main/resources:
title=Welcome
message=Hello! I hope you're having a great day.
This all works great. To enable hot-reload, I added devtools to pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
And installed the LiveReload extension for Firefox.
I restarted my server, enabled LiveReload and navigated to http://localhost:8080. I tried changing and saving both home.html and messages.properties and refreshing my browser. The output in the browser does not change. Is there something else I need to do to disable caching of Thymeleaf templates and message bundles in Spring Boot 2.1?
Devtools will disable caching so that an update to the template file can be reconsidered when it needs to be rendered again.
When your application starts in a JVM process though, there is nothing pointing to your source files and it can only see the classpath. So whatever change you make to a source file needs to be updated to the classpath location, which usually happens by asking your IDE to "Build the project".
So the missing step for the template is that and if the documentation is not clear about that, feel free to open an issue with a suggestion as we've been iterating on that quite a lot.
There is nothing specific about i18n though. If you change them and update the classpath we'll restart the app rather than picking this up the same way we do for templates. We did try to support this once, see this issue for more details. Having said that, you shouldn't expect that a change to a resource file "will just work". A change to configuration will obviously require the app to restart for instance (again, by updating the classpath when you use devtools).
Some added note about IDEs support:
Eclipse incrementally compiles and copies changed files on "save". So if you save your template you should be good to go
IntelliJ IDEA Ultimate has dedicated devtools support as of 2018.1 - If you configure "On frame deactivation" to "Update resources" it will do the right thing when you switch to your browser. Before that support I had a special keystroke mapped to "Build Project" (incrementally compiles and copies resources) that I invoked whenever I wanted my changes to be reflected
If you're not using an IDE, you need to have something to update the classpath for you. We've tried to support that out-of-the-box but turned out to be quite complex. There is a comment to help you if you're using Gradle.
Add the following to your application.properties :
spring.thymeleaf.cache=false

How to do component scanning for sibling package in Spring Boot

Currently I have quite a bit of services written in Spring Boot 2.1.3 (in mono-repo) and I have a common package that's used in most of the services.
So my packages are organized in the following:
root
root.common
root.serviceA
root.serviceA.<subpackages>
root.serviceB
root.serviceB.<subpackages>
...
root.serviceX
root.serviceX.<subpackages>
In each service I have Program.java where it's tagged with #SpringBootApplication (e.g. root/serviceA/Program.java)
The problem now I'm having is that I have a component in root.common (e.g. root/common/JSONSerializer.java) which needs to be loaded in all the services. I tried tagging the file with #JsonComponent but obviously it doesn't work because it's outside root.service* package.
I managed to get it working by manually adding #Import tag in the main file but that means that for each service I have to manually add #Import({root.common.JSONSerializer.class}) which is tedious and error prone. Is there a way to include this file in the component scanning process?
You can set each Program class by following way:
#SpringBootApplication(scanBasePackages = {"root.serviceA", "root.common"})
REFERENCES
SpringBootApplication documentation

Java MVC project in Spring Tool Suite additional files

I'm learning to make Java MVC project using Spring Tool Suite tool.
The path to make new project is:
File->New->SpringLegacyProject->Spring MVC Project.
My question is: which directory I have to use to add additional not-Spring files and where and what do I have to type for Spring files to see them?
For example:
css files - where to put and how to make jsp views see them, will 'link rel="" 'tag be enough?
properties files used to specify database connection or to specify messages for ReloadableResourceBundleMessageSource. In this case, do I have to create bean for this class in root-context.xml?
Thanks.
You should probably use Spring Boot (i.e. use File->New->Spring Starter Project and select Web as a starter. Place your web resources under src/main/resources/static folder. They are picked up automatically from that folder.
You should try an example project: File -> New -> Import Spring Getting Started Content and then pick "Serving Web Content" from the list.
Try some DB getting started content example to get the answer for the second part of your question.

Using Spring boot/cloud with Amazon AWS lambda does not inject values

I have an AWS lambda RequestHandler class which is invoked directly by AWS. Eventually I need to get it working with Spring Boot because I need it to be able to retrieve data from Spring Cloud configuration server.
The problem is that the code works if I run it locally from my own dev environment but fails to inject config values when deployed on AWS.
#Configuration
#EnableAutoConfiguration
#ComponentScan("my.package")
public class MyClass implements com.amazonaws.services.lambda.runtime.RequestHandler<I, O> {
public O handleRequest(I input, Context context) {
ApplicationContext applicationContext = new SpringApplicationBuilder()
.main(getClass())
.showBanner(false)
.web(false)
.sources(getClass())
.addCommandLineProperties(false)
.build()
.run();
log.info(applicationContext.getBean(SomeConfigClass.class).foo);
// prints cloud-injected value when running from local dev env
//
// prints "${path.to.value}" literal when running from AWS
// even though Spring Boot starts successfully without errors
}
}
#Configuration
public class SomeConfigClass {
#Value("${path.to.value}")
public String foo;
}
src/main/resources/bootstrap.yml:
spring:
application:
name: my_service
cloud:
config:
uri: http://my.server
failFast: true
profile: localdev
What have I tried:
using regular Spring MVC, but this doesn't have integration with #Value injection/Spring cloud.
using #PropertySource - but found out it doesn't support .yml files
verified to ensure the config server is serving requests to any IP address (there's no IP address filtering)
running curl to ensure the value is brought back
verified to ensure that .jar actually contains bootstrap.yml at jar root
verified to ensure that .jar actually contains Spring Boot classes. FWIW I'm using Maven shade plugin which packages the project into a fat .jar with all dependencies.
Note: AWS Lambda does not support environment variables and therefore I can not set anything like spring.application.name (neither as environment variable nor as -D parameter). Nor I can control the underlying classes which actually launch MyClass - this is completely transparent to the end user. I just package the jar and provide the entry point (class name), rest is taken care of.
Is there anything I could have missed? Any way I could debug this better?
After a bit of debugging I have determined that the issue is with using the Maven Shade plugin. Spring Boot looks in its autoconfigure jar for a META-INF/spring.factories jar see here for some information on this. In order to package a Spring Boot jar correctly you need to use the Spring Boot Maven Plugin and set it up to run during the maven repackage phase. The reason it works in your local IDE is because you are not running the Shade packaged jar. They do some special magic in their plugin to get things in the right spot that the Shade plugin is unaware of.
I was able to create some sample code that initially was not injecting values but works now that I used the correct plugin. See this GitHub repo to check out what I have done.
I did not connect it with Spring Cloud but now that the rest of the Spring Boot injection is working I think it should be straightforward.
As I mentioned in the comments you may want to consider just a simple REST call to get the cloud configuration and inject it yourself to save on the overhead of loading a Spring application with every request.
UPDATE: For Spring Boot 1.4.x you must provide this configuration in the Spring Boot plugin:
<configuration>
<layout>MODULE</layout>
</configuration>
If you do not then by default the new behavior of the plugin is to put all of your jars under BOOT-INF as the intent is for the jar to be executable and have the bootstrap process load it. I found this out while addressing adding a warning for the situation that was encountered here. See https://github.com/spring-projects/spring-boot/issues/5465 for reference.

Dynamic Web Application - platform with components

I am doing a research on how to make a proper structure for my web application.
It will be a web application serving as a platform for additional, independent components.
The components must be able to map requests by using the #Controller annotaion.
So far I have learned, that:
The platform will be deployed as a .war file on Tomcat.
The platform classpath location will contain components in a form of .jar files.
My question is:
How to setup the components and the platform, so that platform will make use of the components' #Controllers?
So far I have the platform.war running on Tomcat. It is annotation based Spring configuration.
I also have the first component, it is a single Java class with #Controller annotation and first mapping. For some reason when I include this component in the classpath of the platform and try to access the url mapped in the component, the application returns 404 error. In the log files it says "No mapping found for HTTP request" so it does not initialize the component's #Controller.
For further explanation click here.
In your JAR file, create a package defining your namespace, i.e: "com.platformproject.web". Then all you need to do is put the JAR file in WEB-INF/lib (or better use Maven Modules) and scan the annotations at startup:
MvcConfig.java
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "com.platformproject.web" })
public class MvcConfig extends WebMvcConfigurerAdapter { ... }

Categories