SpringBoot and JSON using PUT - json

I'm facing a little situation using SpringBoot and a PUT request. All is working fine concerning GET. I try to send a PUT request passing an object as JSON (testing using postman).
Maven configuration:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Here is my POJO:
public final class Request
{
private String name;
private Boolean lock;
//...public getter and setters...
}
Here is my Controller:
#RestController
#RequestMapping("/controller")
public class Controller
{
#RequestMapping(value = "locking", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public static synchronized Object lock(Request request)
{
System.out.println("name:"+request.getName());
System.out.println("lock:"+request.getLock());
return null;
}
}
My input is (using postman):
http://localhost:8080/controller/locking
request type: PUT
Content-Type: application/json
Content:{"name":"test","lock":true}
My output is:
name:null
lock:null
Again a simple GET works just fine.
Any idea on what I'm missing here?

Related

Cucumber With JUnit Undefined Step Exception

I'm new to the UnitTesting and Cucumber, and today I tried to implement a simple example from a tutorial in Eclipse and I got error when I try run the RunnerClass.java.
My Pom file
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>belajar1</groupId>
<artifactId>belajar1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>9</release>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.0.0-beta4</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.10.2</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.10.2</version>
</dependency>
</dependencies>
</project>
My feature file
Feature: Gmail Testing
Scenario: Gmail Login
Given url opened
Then enter user id and click next
Then enter password
And click login
Scenario: Gmail Close
Then Close browser
My Definition file
public class stepDefinition {
public static WebDriver obj=null;
#Given("^url opened$")
public void url_opened() throws Throwable{
System.setProperty("webdriver.gecko.driver","D:\\Installed APP\\Eclipse Workspace\\Webdriver\\geckodriver.exe");
obj=new FirefoxDriver();
obj.manage().window().maximize();
obj.get("https://mail.google.com");
}
#Then("enter user id and click next")
public void enter_user_id_and_click_next() throws InterruptedException{
obj.findElement(By.id("Email")).sendKeys("YOURUSERID");
obj.findElement(By.id("next")).click();
Thread.sleep(2000);
}
#Then("^enter password$")
public void enter_password(){
obj.findElement(By.id("Passwd")).sendKeys("YOURPASSWORD");
}
#Then("^click login$")
public void click_login() throws InterruptedException{
obj.findElement(By.id("signIn")).click();
Thread.sleep(6000);
}
#Then("^close browser$")
public void close_browser(){
obj.quit();
}
}
My Runner file
package tester;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features="src/test/resources/demo.feature",
glue="definition.stepDefinition",
plugin = {
"pretty",
"html:target/report", //create a folder called cucumber
"json:target/report.json",
//Notice the corresponding file extension (.json) telling cucumber to create a file
// "com.cucumber.listener.ExtentCucumberFormatter:target/report.html"
//Notice I remove the white space at :target/report.html
}
)
public class RunnerClass {
}
I keep got this error
enter image description here
Also this my Library
enter image description here

Spring-boot 2 and swagger 2 (springfox) does not show model

I have created my patch endpoint (Json path specified in RFC 6902).
At UI generated by springfox my endpoint is shown, but the model example (only patch) did not show.
To use Json patch in my Spring-boot 2 project I have used that dependency on pom.xml.
<dependencies>
<dependency>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-patch</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
At my endpoint, my code is:
#RestController
#RequestMapping(value = "/operation", produces = "application/json")
public class IntentController {
#RequestMapping(value = "/{id}",
method = RequestMethod.PATCH,
consumes = "application/json-patch+json")
public void updateValue(#PathVariable Long id, #RequestBody JsonPatch patch){ {
// ... do magic
}
#RequestMapping(value = "/{id}",
method = RequestMethod.GET)
public MyDto getValue(#PathVariable Long id){ {
MyDto dto = service.findById(id);
return dto;
}
#RequestMapping(method = RequestMethod.POST)
public void updateValue(#RequestBody MyDto dto){ {
service.insert(dto);
}
}
My GET and POST endpoints are generated fine with their example models in UI.
Only PATCH doesn't work fine... their example model didn't generate.
The problem lies with JsonPatch object, this object does not have any getter method, so Springfox library could not generate the model for request.
One possible solution may be like , you create a custom MyJsonPatch POJO with getter and setter and create a JsonPatch with the data of MyJsonPatch.
I can't found a solution to my problem, so I decided to use #ApiParam from Swagger to describe that this field is an RFC 6902 implementation.

Issue creating tables in JPA

I am working an assignment for a class, and am having trouble getting tables to be created in my MySQL database from entities in java. I am trying to get the tables to be created by typing mvn clean install in the project folder in terminal (which is what was given to me as an example to create them once I had the entities in java). No errors or anything occur, and I get a "build successful" message in terminal, but no new tables are created in MySQL. I have confirmed that my endpoint/username/password are all working by setting up the project using jdbc to manually connect instead of JPA and everything works fine that way. Note: This isn't the actual content of the assignment just the initial setup. I've followed the instructions the professor has given multiple times and it is not working. Thanks for the help!
I created my project using the spring command line interface in terminal:
spring init --dependencies=web test
I then added a webapp directory with a index.html file in the src/main directory of the project. Then the project was imported to IntelliJ as a Maven project
I added the following to my application.properties file which is in src/main resources (and is the resources root of the project). The aws endpoint/schema name are also filled in as usual:
spring.datasource.url=jdbc:mysql://MyAWSEndpoint:3306/SchemaName
spring.datasource.username=MyUsername
spring.datasource.password=MyPassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
I then have a class that I created called random which is contained in src/main/java which is my source root for the project.
package com.example.test;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class random {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Additionally I have a Repository I made for the entity in java contained in the same package as the class above.
package com.example.test;
import org.springframework.data.repository.CrudRepository;
public interface RandomRepository extends CrudRepository<random, Integer> {
}
Here is my pom.xml file as well
<?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>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Additionally, I have a an application file in src/main/java:
package com.example.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
You might want to use the below property in the application.properties once:
spring.jpa.hibernate.ddl-auto=create
after the first run you can comment it out again.
To be sure your db user must have the correct privileges to create tables otherwise it won't work :-)
And you need to run the application either by using:
mvn clean package && java -jar target/test-0.0.1-SNAPSHOT.jar
or
mvn clean spring-boot:run
if your application is only build it will not run and not do anything except being compiled and tested.
It might be that your teacher had the setup of the database in the unit tests? then it would have been done...
Good luck

Jersey 2 InjectLink is ignored

I'm creating a new Jersey 2.21, Jackson 2.6.1 REST server (I tried with Jersey 2.19 and Jackson 2.5.3 as well) and a want to use #InjectLink to provide HATEOAS links (like 'self') for my callers. The most basic app (taken from Jersey doc and Jersey sample apps) isn't working, and I can't figure out why.
I started by taking the basic Widgets class from the Jersey doc, but the JSON or XML returned is just an empty structure.
XML:
<Widgets/>
JSON:
{}
Widgets.java
package org.glassfish.jersey.examples.linking;
import java.net.URI;
import java.util.List;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlRootElement;
import org.glassfish.jersey.linking.InjectLink;
import org.glassfish.jersey.linking.InjectLinks;
#XmlRootElement()
public class Widgets {
#InjectLink(resource=WidgetsResource.class)
URI u;
#InjectLinks({#InjectLink(resource=WidgetsResource.class, rel = "self")})
List<Link> links;
public Widgets() {}
}
I put a breakpoint in the resource code and examined the object being returned. it.links and it.u are both null. There's nothing injected.
WidgetsResource.java
#Path("widgets")
public class WidgetsResource {
#GET
public Widgets get() {
Widgets it = new Widgets();
return it;
}
}
Maven dependencies:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-declarative-linking</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-xml-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-yaml-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<properties>
<jersey.version>2.21</jersey.version>
<jackson.version>2.6.1</jackson.version>
</properties>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>Server</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.glassfish.jersey.examples.linking.Server</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/v1/*</url-pattern>
</servlet-mapping>
</web-app>
The application object:
package org.glassfish.jersey.examples.linking;
import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;
public class Server extends ResourceConfig {
public Server() {
packages("org.glassfish.jersey.examples.linking",
"com.fasterxml.jackson.jaxrs")
.register(DeclarativeLinkingFeature.class);
}
}
It appears that the #InjectLink(s) annotations are simply being ignored. There must be some magic setting I'm missing, but I've done everything the Jersey doc says to do.
I tried with both Servlet 2.x (shown) and Servlet 3.x (using #ApplicationPath) and that made no difference.
Some of you will notice from my package names that I also tried the slightly more advanced, but no more successful, Jersey declarative linking example (https://github.com/jersey/jersey/tree/master/examples/declarative-linking). Some of the basic fields were returned, but all of the injected links were missing or null.
.../Server/rest/v1/items/1 produced:
{
"id": "1",
"nextId": "2",
"prevId": "0",
"prev": true,
"next": true
}
FYI - I'm running Java 1.8.0_60, Eclipse Mars, and Tomcat 8.0.26. There are no errors, no warnings and no runtime messages. I'm completely stumped. Anyone have any pointers???
I have added the following to my servlet config:
`<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.linking.DeclarativeLinkingFeature
</param-value>
</init-param>'
and the links were rendered in the json response.
For information, if you do not want to use web.xml config file, you can do that:
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;
#ApplicationPath("rest/v1")
public class MyApp extends ResourceConfig {
public MyApp () {
packages("the.package.where.your.services.are.located")
.register(DeclarativeLinkingFeature.class);
}
}

Spring 3.1.1 and json getting error 406

I have written a simple rest based controller using #responseBody which I expect to return a JSON.
Somehow I am not able to get it work as expected.
when I run the url "http://localhost:8080/my-webapp/amazon/rips" ..it throws back below error
HTTP Status 406 -JBWEB000126: The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request 'Accept' headers.
can someone please lend a helping hand.
Mycontroller is below:
#Controller
#RequestMapping("/amazon")
public class JsonController {
#RequestMapping(value="/{name}", method = RequestMethod.GET,produces = "application/json")
public #ResponseBody
Book getShopInJSON(#PathVariable String name) {
Book book = new Book();
book.setName(name);
book.setAvailablity(false);
return book;
}
Book class is below:
public class Book {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isAvailablity() {
return availablity;
}
public void setAvailablity(boolean availablity) {
this.availablity = availablity;
}
private String name ;
private boolean availablity;
}
displatcher servlet is as below:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.rips.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
with the help from #CodeChimp I realized that request that I was sending was not having proper accept headers.
I used Chromes "Advanced Rest client" and added headers with key ="accept" and value ="application/json",I was able to get proper response.
update
I found that <mvc:annotation-driven /> was not added in the dispatcher servlet which configures the support for HTTP message conversion with #RequestBody/#ResponseBody.Once I added this piece of info there was no need to use any advanced Rest client.