How to create RESTful web services using SPRING, GRADLE & ECLIPSE
* First install Eclipse in your machine by referring to the official wiki (I have installed an eclipse version called Kepler in my machine)
* After installing Eclipse, open it and go to "eclipse market place" to add Gradle as seen in below screenshots:
* Now create a new blank Gradle project in Eclipse
*Now lets build the blank project using Gradle to ensure that everything is fine so far
* Now change the build.gradle file to below as seen in http://spring.io/guides/gs/rest-service/
buildscript {
repositories {
maven { url "http://repo.spring.io/libs-release" }
mavenLocal()
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.4.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
jar {
baseName = 'gs-rest-service'
version = '0.1.0'
}
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/libs-release" }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("junit:junit")
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
* We can now delete the default java files created as a part of blank project
* Now add Spring webservice files as per official spring website http://spring.io/guides/gs/rest-service/
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", required=false, defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
package hello;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
directory structure in eclipse will look like this
as seen above, eclipse shows in some errors in the files (see red marks in front of the file). This is because spring jar files are not yet there in the eclipse classpath.
In order to download the dependencies we can just go to the Gradle menu as shown below and click on refresh dependencies
as seen below the red errors are gone now after dependencies are refreshed - thanks to Gradle for making dependency management this so easy - it used to be done in ant previously by manually downloading each jar file
*We are done now! lets run the server by executing Application class in eclipse
* Lets checkout that the results look ok by running the following url in our browser: http://localhost:8080/greeting
Result looks something like this:
You also run http://localhost:8080/greeting?name=Bhajan to pass a parameter the the webservice. This is how it looks after passing the parameter:
* Now there is one more way by which we can pass parameters in RESTful urls.
If we use that way then the URL will look something like this http://localhost:8080/greeting/Bhajan
(This link gives more details on understanding REST)
so to change it to the new way, change the GreetingController as seen below
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
//The two lines below have been changed
@RequestMapping(method = RequestMethod.GET, value = "greeting/{name}")
public Greeting greeting(@PathVariable String name){
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
* Stop the server by clicking on red button as seen below
* I am trying to rebuild by running Gradle build again but i am getting the following error now
[sts] -----------------------------------------------------
[sts] Starting Gradle build for the following tasks:
[sts] :build
[sts] -----------------------------------------------------
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:bootRepackage
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test
org.gradle.PersonTest > canConstructAPersonWithAName FAILED
java.lang.NoClassDefFoundError at PersonTest.java:9
Caused by: java.lang.ClassNotFoundException at PersonTest.java:9
1 test completed, 1 failed
:test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at: file:///C:/Users/bsingh/workspace/MySpringWS/build/reports/tests/index.html
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 2.611 secs
[sts] Build failed
org.gradle.tooling.BuildException: Could not execute build using Gradle distribution 'http://services.gradle.org/distributions/gradle-1.10-bin.zip'.
In order to debug when I build I will use debug mode:
Now when i build again i see the following message somewhere in the log
21:31:22.604 [QUIET] [system.out] 21:31:22.603 [INFO] [org.gradle.api.internal.tasks.testing.worker.TestWorker] Gradle Worker 1 finished executing tests.
21:31:22.614 [QUIET] [system.out] 21:31:22.610 [DEBUG] [org.gradle.process.internal.child.ActionExecutionWorker] Completed Gradle Worker 1.
21:31:22.630 [DEBUG] [TestEventLogger]
21:31:22.631 [DEBUG] [TestEventLogger] org.gradle.PersonTest > canConstructAPersonWithAName FAILED
21:31:22.633 [DEBUG] [TestEventLogger] java.lang.NoClassDefFoundError: org/gradle/Person
21:31:22.633 [DEBUG] [TestEventLogger] at org.gradle.PersonTest.canConstructAPersonWithAName(PersonTest.java:9)
21:31:22.634 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
21:31:22.634 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
21:31:22.635 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
So I see that there is still a function called canConstructAPersonWithAName in org.gradle.PersonTest from the blank project that we created in the start. This is causing error.
In order to resolve this i will just run the clean target and then the build target in Gradle
* Now run the server again by executing Application class in eclipse
And this is the way i can call my webservice now...
That's it!
Details of the application we built are in http://spring.io/guides/gs/rest-service/
Enjoy the Spring!
--Bhajan
Comments