400 Bad Request when posting JSON Array to a Spring controller - rest

I have been successful in sending a simple JSON object over to a spring framework Controller
curl -v -H "Content-Type: application/json" -H "Accept: application/json" -d '{"lastName":"Smith","firstName":"John"}' http://localhost:8080/WebServices02/aura/testJsonArray
However, when I send over a JSON object with an embedded array
curl -v -H "Content-Type: application/json" -H "Accept: application/json" -d '{"lastName":"Smith","pals":[{"name":"Billy"}],"firstName":"John"}' http://localhost:8080/WebServices02/aura/testJsonArray
I get the error 400 'The request sent by the client was syntactically incorrect ().'
My controller is
#Controller
#RequestMapping(value="/aura")
public class AuraController {
#RequestMapping(value = "/testJsonArray", method = RequestMethod.POST, headers = {"content-type=application/json"})
#ResponseBody
public void testJsonArray(#RequestBody Aura aura){
System.err.println("Called testJsonArray(): " + "Aura is " + aura.toString());
}
}
My Aura class is defined as
import java.io.Serializable;
import java.util.List;
import org.json.JSONObject;
public class Aura implements Serializable {
public class Pal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
private List<Pal> pals;
public String toString(){
return new JSONObject(this).toString();
}
public List<Pal> getPals() {
return pals;
}
public void setPals(List<Pal> pals) {
this.pals = pals;
}
}
My bean (under mvc:message-converters) is
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
If someone can help me on this... thanks

You have to include Jackson JSON Mapper dependency for jackson-core-asl and jackson-mapper-asl in your project.
This is necessary for mapping json with java pojo class fields.

Related

NullPointerException accessing entity by ID when #CreatedBy auditing is used

I just added a relation with #CreatedBy to one of my entites and since then, I receive a NullPointerException accessing it via ID. But first things first:
The entity. I am leaving out some fields but left the "owner" in place, since the stack trace (see below) refers to that. The "creator" is the relation I added.
#Entity
#Data
#NoArgsConstructor
#EntityListeners(AuditingEntityListener.class)
public class Invitation implements BaseEntity<Long>, OwnedEntity {
#Id
#GeneratedValue
private Long id;
#NotNull
#ManyToOne
private Company owner;
#CreatedBy
#OneToOne
private Account creator;
...
}
The "creator" field is set by my implementation of AuditorAware which looks like this:
#Component
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class AuditorProvider implements AuditorAware<Account> {
private static final Log LOG = LogFactory.getLog(AuditorProvider.class);
private final #NonNull AccountRepo accountRepo;
#Override
public Optional<Account> getCurrentAuditor() {
Optional<Account> opt = accountRepo.findMe();
if (opt.isPresent()) {
LOG.debug("Found auditor: " + opt.get());
} else {
LOG.debug("No auditor found.");
}
return opt;
}
}
The method accountRepo.findMe() finds the current instance of Account based on the security context.
With this in place, when I POST an Invitation entity like
curl -XPOST -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" localhost:8081/invitations -d '{"email":"k#lo.de","role":"http://localhost:8081/roles/139"}'
the response body looks good:
{
"email" : "k#lo.de",
"_links" : {
"self" : {
"href" : "http://localhost:8081/invitations/144"
},
"invitation" : {
"href" : "http://localhost:8081/invitations/144"
},
"creator" : {
"href" : "http://localhost:8081/invitations/144/creator"
},
"role" : {
"href" : "http://localhost:8081/invitations/144/role"
},
"owner" : {
"href" : "http://localhost:8081/invitations/144/owner"
}
}
}
The database table for Invitations and the logs show that the "creator" has successfully been set.
Fetching all invitations works perfectly fine without any errors:
curl -v -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" http://localhost:8081/invitations
Fetching that Invitation with ID 144 gives me an HTTP 500 error:
curl -v -H "Authorization: Bearer $TOKEN" -H "Content-type: application/hal+json" http://localhost:8081/invitations/144
Looking into the logs, I see this stack trace: https://pastebin.com/mVzHHddU
The reason I left the "owner" relation in the snippet above is this line:
at training.edit.identity.model.Company.hashCode(Company.java:22) ~[classes/:na]
Other than that, none of the lines are familiar to me and I cannot make any sense out of the error.
Any ideas would be highly appreciated!
Edit: The company entity
#Data
#NoArgsConstructor
#Entity
public class Company implements BaseEntity<Long>, OwnedEntity {
#Id
#GeneratedValue
private Long id;
#NotNull
private String name;
#NotNull
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<Address> addresses = new HashSet<Address>();
public boolean addAddress(Address address) {
return this.addresses.add(address);
}
#JsonIgnore
#Override
public ScopedEntity getParent() {
return null;
}
#JsonIgnore
#Override
public Set<Company> getTenants() {
return Sets.newHashSet(this);
}
#Override
public void configureTenant(Company tenant) {
throw new RuntimeException("Cannot configure tenant on Company.");
}
}
Edit: Because of the lombok related comment below, I removed the #Data annotation from Company and created the getters and setters manually. Like this, fetching an Invitation by ID works.
Does that make sense to anyone?

RESTEasy Could not find MessageBodyWriter for response object of type: <Entity Class> of media type: application/json

I'm trying to implement a rest endpoint using rest easy. This is a GET endpoint,
#Controller
#Path("/api")
public class TestController {
private static final Log LOG = LogFactory.getLog(TestController .class);
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public Response getTest() {
LOG.info(" inside test");
Response r = null;
try {
Test test = new Test();
test.setId(1L);
test.setName("test");
test.setAge("20");
r = Response.ok(test).build();
} catch (Exception e){
LOG.error(e);
}
return r;
}
}
Below is the entity class which I'm trying to return
#XmlRootElement
public class Test {
#XmlElement(name = "id")
private Long id;
#XmlElement(name = "name")
private String name;
#XmlElement(name = "age")
private String age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
Getting below error when the endpoint is called from a rest client.
Could not find MessageBodyWriter for response object of type: com.package.Test of media type: application/json
These are some dependencies I have added which I believe would be useful for this.
httpclient-4.0.3.jar
httpcore-4.0.1.jar
jackson-core-asl-1.6.3.jar
jackson-jaxrs-1.9.13.jar
jackson-jaxrs-json-provider-2.2.1.jar
jackson-mapper-asl-1.6.3.jar
jackson-xc-1.6.3.jar
jaxrs-api-3.0.12.Final.jar
jboss-logging-3.3.1.Final.jar
jcip-annotations-1.0.jar
resteasy-jaxb-provider-3.1.0.Final.jar
resteasy-jettison-provider-2.3.1.GA.jar
resteasy-spring-2.2.1.GA.jar
scannotation-1.0.3.jar
Does anyone has an idea why this kind of error coming. endpoint is able return a plain string as a response.
jackson-jaxrs-json-provider contains the MessageBodyReader/Writer to handle JSON/POJO conversion. But you still need to register its JacksonJaxbJsonProvider with your application.
If you are using RESTEasy, you can also just add the resteasy-jackson-provider dependency to your project and it will automatically register the JacksonJaxbJsonProvider so you don't need to explicitly do it. The dependency also adds a few other useful items. So your best bet is to just add the dependency.

save data to the database using spring boot

when I post the data using the postman, the server replies with error code 500. the NetBeans terminal show:(java.sql.SQLIntegrityConstraintViolationException: Column 'email' cannot be null)
bellow my entityclass:
#Entity(name="user")
public class UserEntity {
#Id
#GeneratedValue
private long id;
#Column(nullable = true)
private String userId;
#Column(nullable = true)
private String FirstName;
#Column(nullable = true)
private String LastName;
#Column(nullable = true)
private String Email;
#Column(nullable = true)
private String Password;
#Column(nullable = true)
private String encryptedPassword;
#Column()
private String emailVerificationToken;
#Column()
private Boolean emailVerificationStatus=false;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String FirstName) {
this.FirstName = FirstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String LastName) {
this.LastName = LastName;
}
public String getEmail() {
return Email;
}
public void setEmail(String Email) {
this.Email = Email;
}
public String getPassword() {
return Password;
}
public void setPassword(String Password) {
this.Password = Password;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public String getEmailVerificationToken() {
return emailVerificationToken;
}
public void setEmailVerificationToken(String emailVerificationToken) {
this.emailVerificationToken = emailVerificationToken;
}
public Boolean getEmailVerificationStatus() {
return emailVerificationStatus;
}
public void setEmailVerificationStatus(Boolean emailVerificationStatus) {
this.emailVerificationStatus = emailVerificationStatus;
}
}
bellow is my service implementation class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.example.mobile.demo.impl;
import com.example.mobile.demo.DTo.UserDto;
import com.example.mobile.demo.Entity.UserEntity;
import com.example.mobile.demo.repository.UserRepository;
import com.example.mobile.demo.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* #author iphone
*/
#Service
public class UserserviceImpl implements UserService{
#Autowired
UserRepository userRepository;//it is in the data layer so we need the repository to save in the database
#Override
public UserDto createuser(UserDto user) {
UserEntity userentity=new UserEntity();
BeanUtils.copyProperties(user, userentity);
System.out.println("the properties has been copied to the entity");
userentity.setEncryptedPassword("test");
userentity.setUserId("testID");
System.out.println("encryptef passwird and user id has been set");
UserEntity stotedValue=userRepository.save(userentity);
UserDto returnValue=new UserDto();
BeanUtils.copyProperties(stotedValue, returnValue);
return returnValue;
}
}
my model class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.example.mobile.demo.modoel;
/**
*
* #author iphone
*/
public class Model {
private String FirstName;
private String LastName;
private String Email;
private String Password;
public String getFirstName() {
return FirstName;
}
public void setFistName(String FirstName) {
this.FirstName = FirstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String LastName) {
this.LastName = LastName;
}
public String getEmail() {
return Email;
}
public void setEmail(String Email) {
this.Email = Email;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
this.Password = password;
}
}
bellow is what Iam sending in the post request in the postman:
{
"FirstName":"jack",
"LastName":"testjack",
"Password":"124",
"Email":"emailTest#gmail.com"
}
The issue is in json to java Model mapping.
You need to rename your Model.java properties in this way:
Email -> email
FirstName -> firstName
Or add #JsonProperty("name"):
#JsonProperty("email")
private String Email;
Don't forget json changes, if you choose properties renaming:
{
"firstName":"jack",
"lastName":"testjack",
"password":"124",
"email":"emailTest#gmail.com"
}

Convert Java object to BigQuery TableRow

I am exploring Google Cloud Dataflow.
I was wondering if automatic conversion between java object or JSON to TableRow can be done.
Just like we can automatically parse JSON to POJO class.
I could not find relevant information.
Hope not to duplicate question.
Will be grateful for any info!
Greetings
I've looking for examples for the same with no luck. I created a POJO class that almost match the schema of the bigquery table and matches the structure of the JSON objects that are the input for the pipeline. Finally, when I have to convert those objects to TableRow, for the nested and repeated values I made something like below, and the conversion was made by the API
TableRow row = new TableRow()
.set("items", c.element().getItems())
.set("orderDate", c.element().getOrderDate())
.set("orderNumber", c.element().getOrderNumber());
Where Item class is part of the Order object :
#JsonProperty("items")
private List<Item> items = null;
This is the code for Item class:
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"id",
"code",
"detail",
"name",
"shortName",
"description",
"sku",
"quantity",
"category",
"products"
})
public class Item implements Serializable
{
#JsonProperty("id")
private Integer id;
#JsonProperty("code")
private String code;
#JsonProperty("detail")
private String detail;
#JsonProperty("name")
private String name;
#JsonProperty("shortName")
private String shortName;
#JsonProperty("description")
private String description;
#JsonProperty("sku")
private String sku;
#JsonProperty("quantity")
private Integer quantity;
#JsonProperty("category")
private Category category;
#JsonProperty("products")
private List<Product> products = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
private final static long serialVersionUID = -5644586446669059821L;
#JsonProperty("id")
public Integer getId() {
return id;
}
#JsonProperty("id")
public void setId(Integer id) {
this.id = id;
}
#JsonProperty("code")
public String getCode() {
return code;
}
#JsonProperty("code")
public void setCode(String code) {
this.code = code;
}
#JsonProperty("detail")
public String getDetail() {
return detail;
}
#JsonProperty("detail")
public void setDetail(String detail) {
this.detail = detail;
}
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
#JsonProperty("shortName")
public String getShortName() {
return shortName;
}
#JsonProperty("shortName")
public void setShortName(String shortName) {
this.shortName = shortName;
}
#JsonProperty("description")
public String getDescription() {
return description;
}
#JsonProperty("description")
public void setDescription(String description) {
this.description = description;
}
#JsonProperty("sku")
public String getSku() {
return sku;
}
#JsonProperty("sku")
public void setSku(String sku) {
this.sku = sku;
}
#JsonProperty("quantity")
public Integer getQuantity() {
return quantity;
}
#JsonProperty("quantity")
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
#JsonProperty("category")
public Category getCategory() {
return category;
}
#JsonProperty("category")
public void setCategory(Category category) {
this.category = category;
}
#JsonProperty("products")
public List<Product> getProducts() {
return products;
}
#JsonProperty("products")
public void setProducts(List<Product> products) {
this.products = products;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
And this is the schema of the BigQuery table in regards Items, where Item is a RECORD and REPEATED field and also contain a nested RECORD and REPEATED field: products. See the screenshot of the schema
Item schema fields in BQ

Neo4j Springboot SpringData restful example not complete without relationship entity

I am using the springio accessing-neo4j-data-rest example which has the relationship as part of the Person class and really doesn't show the advantage of Neo4j. I tried creating a Family relationship entity, but can't create a relationship using a restful service with Springboot and port 8080.
My service works and creates the relationship using http://localhost:7474/db/data/node/67/relationships
Shouldn't I be able to do this (where 66 and 67 are existing Person entities):
POST to http://localhost:8080/people/67/family
{
"to" : "http://localhost:8080/people/66",
"type" : "RELATED_TO"
}
I get the error:
{
"timestamp": 1486948326367,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/people/67/family"
}
Person.java
package hello;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
#NodeEntity
public class Person {
#GraphId public Long id;
private String firstName;
private String lastName;
#Relationship(type = Family.TYPE, direction = Relationship.UNDIRECTED)
private Set<Family> family = new HashSet<Family>();
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Set<Family> getFamily() {
return family;
}
public void addFamily(Family f) {
family.add(f);
}
public void addFamily(Person target, String association) {
this.family.add(new Family(this, target, association));
}
public void addFamily(Person target) {
this.family.add(new Family(this, target));
}
}
Family.java
package hello;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;
#RelationshipEntity(type = Family.TYPE)
public class Family {
public static final String TYPE = "RELATED_TO";
#GraphId
private Long id;
#Property
private String association;
#StartNode
private Person p1;
#EndNode
private Person p2;
public Family() {
}
public Family(Person first, Person second) {
this.p1 = first;
this.p2 = second;
}
public Family(Person first, Person second, String assoc) {
this.p1 = first;
this.p2 = second;
association = assoc;
}
public Long getId() {
return id;
}
public Person getFirst() {
return p1;
}
public Person getSecond() {
return p2;
}
public String getAssociation() {
return association;
}
public void setAssociation(String association) {
this.association = association;
}
}
PersonRepository.java
package hello;
import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
List<Person> findByFirstName(#Param("name") String name);
}
FamilyRepository .java
package hello;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource(collectionResourceRel = "family", path = "family") // what should go here????
public interface FamilyRepository extends GraphRepository<Family> {
// //creates a get - need a post
// #Query("MATCH (a:Traveler),(b:Traveler) WHERE a.lastName = {from} AND b.lastName = {to} CREATE (a)-[r:RELATED_TO]->(b) RETURN r")
// void worksWith(#Param("to") String to);
}
Edited:2-19-2017 - Getting closer. I needed a controller - something like this:
#RestController
public class FamilyController {
...
#RequestMapping(value = "/people/{id}/family", method = RequestMethod.POST, consumes = APPLICATION_JSON, produces = APPLICATION_JSON)
#ResponseStatus(value = HttpStatus.ACCEPTED)
#ResponseBody
Family addFamily(#RequestBody Family f, #PathVariable(value = "id") String id) {