I am getting:
Cannot get property 'show' on null object in my grails project
Here is my code
package com.djamware
class TestController {
EmployeeService employeeService
def secondaryDataSourceTemplate
def mainDataSourceTemplate
def testService
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index() {
render testService.show
}
def show() {
Employee employee=new Employee();
employee.setName("Gaurav chauhan")
employee.setEmail("chauhankgaurav97#gmail.com")
employee.setPosition("Java Devloper")
employee.setSalary(new Double(15000.0))
String sqlQuery = "SELECT name FROM Employee";
def counti=new Integer(1);
try {
def result = secondaryDataSourceTemplate.queryForList(sqlQuery)
println "result of Query is =====>"+result.name
println "Size of Result ========> "+result.size();
counti=result.size();
}
catch (Exception e) {
e.printStackTrace();
counti=new Integer(10);
}
employeeService.save(employee)
render counti;
}
}
Try including into your static methods the definition for show
static allowedMethods = [show: "GET", save: "POST", update: "PUT", delete: "DELETE"]
Related
My objective is to read a very complex JSON using Spring Batch. Below is the sample JSON.
{
"order-info" : {
"order-number" : "Test-Order-1"
"order-items" : [
{
"item-id" : "4144769310"
"categories" : [
"ABCD",
"DEF"
],
"item_imag" : "http:// "
"attributes: {
"color" : "red"
},
"dimensions" : {
},
"vendor" : "abcd",
},
{
"item-id" : "88888",
"categories" : [
"ABCD",
"DEF"
],
.......
I understand that I would need to create a Custom ItemReader to parse this JSON.
Kindly provide me some pointers. I am really clueless.
I am now not using CustomItemReader. I am using Java POJOs. My JsonItemReader is as per below:
#Bean
public JsonItemReader<Trade> jsonItemReader() {
ObjectMapper objectMapper = new ObjectMapper();
JacksonJsonObjectReader<Trade> jsonObjectReader =
new JacksonJsonObjectReader<>(Trade.class);
jsonObjectReader.setMapper(objectMapper);
return new JsonItemReaderBuilder<Trade>()
.jsonObjectReader(jsonObjectReader)
.resource(new ClassPathResource("search_data_1.json"))
.name("tradeJsonItemReader")
.build();
}
The exception which I now get is :
java.lang.IllegalStateException: The Json input stream must start with an array of Json objects
From similar posts in this forum I understand that I need to use JsonObjectReader. "You can implement it to read a single json object and use it with the JsonItemReader (either at construction time or using the setter)".
How can I do this either # construction time or using setter? Please share some code snippet for the same.
The delegate of MultiResourceItemReader should still be a JsonItemReader. You just need to use a custom JsonObjectReader with the JsonItemReader instead of JacksonJsonObjectReader. Visually, this would be: MultiResourceItemReader -- delegates to --> JsonItemReader -- uses --> your custom JsonObjectReader.
Could you please share a code snippet for the above?
JacksonJsonItemReader is meant to parse from a root node that is already and array node, so it expects your json to start with '['.
If you desire to parse a complex object - in this case, one that have many parent nodes/properties before it gets to the array - you should write a reader. It is really simple to do it and you can follow JacksonJsonObjectReader's structure. Here follows and example of a generic reader for complex object with respective unit tests.
The unit test
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.springframework.core.io.ByteArrayResource;
import com.example.batch_experiment.dataset.Dataset;
import com.example.batch_experiment.dataset.GenericJsonObjectReader;
import com.example.batch_experiment.json.InvalidArrayNodeException;
import com.example.batch_experiment.json.UnreachableNodeException;
import com.fasterxml.jackson.databind.ObjectMapper;
#RunWith(BlockJUnit4ClassRunner.class)
public class GenericJsonObjectReaderTest {
GenericJsonObjectReader<Dataset> reader;
#Before
public void setUp() {
reader = new GenericJsonObjectReader<Dataset>(Dataset.class, "results");
}
#Test
public void shouldRead_ResultAsRootNode() throws Exception {
reader.open(new ByteArrayResource("{\"result\":{\"results\":[{\"id\":\"a\"}]}}".getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
}
#Test
public void shouldIgnoreUnknownProperty() throws Exception {
String jsonStr = "{\"result\":{\"results\":[{\"id\":\"a\", \"aDifferrentProperty\":0}]}}";
reader.open(new ByteArrayResource(jsonStr.getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
}
#Test
public void shouldIgnoreNullWithoutQuotes() throws Exception {
String jsonStr = "{\"result\":{\"results\":[{\"id\":\"a\",\"name\":null}]}}";
try {
reader.open(new ByteArrayResource(jsonStr.getBytes()) {});
Assert.assertTrue(reader.getDatasetNode().isArray());
Assert.assertFalse(reader.getDatasetNode().isEmpty());
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
#Test
public void shouldThrowException_OnNullNode() throws Exception {
boolean exceptionThrown = false;
try {
reader.open(new ByteArrayResource("{}".getBytes()) {});
} catch (UnreachableNodeException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
}
#Test
public void shouldThrowException_OnNotArrayNode() throws Exception {
boolean exceptionThrown = false;
try {
reader.open(new ByteArrayResource("{\"result\":{\"results\":{}}}".getBytes()) {});
} catch (InvalidArrayNodeException e) {
exceptionThrown = true;
}
Assert.assertTrue(exceptionThrown);
}
#Test
public void shouldReadObjectValue() {
try {
reader.setJsonParser(new ObjectMapper().createParser("{\"id\":\"a\"}"));
Dataset dataset = reader.read();
Assert.assertNotNull(dataset);
Assert.assertEquals("a", dataset.getId());
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
}
And the reader:
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.json.JsonObjectReader;
import org.springframework.core.io.Resource;
import com.example.batch_experiment.json.InvalidArrayNodeException;
import com.example.batch_experiment.json.UnreachableNodeException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
/*
* This class follows the structure and functions similar to JacksonJsonObjectReader, with
* the difference that it expects a object as root node, instead of an array.
*/
public class GenericJsonObjectReader<T> implements JsonObjectReader<T>{
Logger logger = Logger.getLogger(GenericJsonObjectReader.class.getName());
ObjectMapper mapper = new ObjectMapper();
private JsonParser jsonParser;
private InputStream inputStream;
private ArrayNode targetNode;
private Class<T> targetType;
private String targetPath;
public GenericJsonObjectReader(Class<T> targetType, String targetPath) {
super();
this.targetType = targetType;
this.targetPath = targetPath;
}
public JsonParser getJsonParser() {
return jsonParser;
}
public void setJsonParser(JsonParser jsonParser) {
this.jsonParser = jsonParser;
}
public ArrayNode getDatasetNode() {
return targetNode;
}
/*
* JsonObjectReader interface has an empty default method and must be implemented in this case to set
* the mapper and the parser
*/
#Override
public void open(Resource resource) throws Exception {
logger.info("Opening json object reader");
this.inputStream = resource.getInputStream();
JsonNode jsonNode = this.mapper.readTree(this.inputStream).findPath(targetPath);
if (!jsonNode.isMissingNode()) {
this.jsonParser = startArrayParser(jsonNode);
logger.info("Reader open with parser reference: " + this.jsonParser);
this.targetNode = (ArrayNode) jsonNode; // for testing purposes
} else {
logger.severe("Couldn't read target node " + this.targetPath);
throw new UnreachableNodeException();
}
}
#Override
public T read() throws Exception {
try {
if (this.jsonParser.nextToken() == JsonToken.START_OBJECT) {
T result = this.mapper.readValue(this.jsonParser, this.targetType);
logger.info("Object read: " + result.hashCode());
return result;
}
} catch (IOException e) {
throw new ParseException("Unable to read next JSON object", e);
}
return null;
}
/**
* Creates a new parser from an array node
*/
private JsonParser startArrayParser(JsonNode jsonArrayNode) throws IOException {
JsonParser jsonParser = this.mapper.getFactory().createParser(jsonArrayNode.toString());
if (jsonParser.nextToken() == JsonToken.START_ARRAY) {
return jsonParser;
} else {
throw new InvalidArrayNodeException();
}
}
#Override
public void close() throws Exception {
this.inputStream.close();
this.jsonParser.close();
}
}
cannot convert from 'System.Web.Mvc.JsonRequestBehavior' to 'Newtonsoft.Json.JsonSerializerSettings'
code
public JsonResult Get()
{
try
{
using (smartpondEntities DB = new smartpondEntities())
{
var pond = DB.Temperatures.OrderByDescending(x => x.WaterTemperature).FirstOrDefault();
return Json(new { success = true, sensorsdata = new { id = pond.WaterTemperature, CurrentTime = pond.CreatedDate } }, JsonRequestBehavior.AllowGet);
}
}
catch (Exception Ex)
{
}
return Json(new { success = false }, JsonRequestBehavior.AllowGet);
}
The second parameter for Json method in Web API controller is incorrectly assigned, since ApiController Json method requires JsonSerializerSettings as second argument:
protected internal JsonResult<T> Json<T>(T content, JsonSerializerSettings serializerSettings)
{
......
}
The MVC controller counterpart for Json method is shown below:
protected internal JsonResult Json(object data, JsonRequestBehavior behavior)
{
......
}
In this case, if the controller class containing Get method above extends ApiController, you need to change 2 return Json statements to return new JsonResult as given below:
public class ControllerName : ApiController
{
public JsonResult Get()
{
try
{
using (smartpondEntities DB = new smartpondEntities())
{
var pond = DB.Temperatures.OrderByDescending(x => x.WaterTemperature).FirstOrDefault();
// return JsonResult here
return new JsonResult()
{
Data = new { success = true, sensorsdata = new { id = pond.WaterTemperature, CurrentTime = pond.CreatedDate }},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
catch (Exception Ex)
{
}
// return JsonResult here
return new JsonResult()
{
Data = new { success = false },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
If you want to use MVC controller when returning JSON instead, change ApiController to Controller class from System.Web.Mvc namespace and keep return Json(...) there.
Similar issue:
JSON return error with ASP
I am trying to send User object to my REST api in json format.
var user={
firstName: "someVal",lastName: "", email: "", contactPhone: "", password: ""
};
var url="http://localhost:8085/MyappName/appliPath/login";
$.ajax({
method:'POST',
contentType: "application/json",
datatype:'json',
url : url,
data:JSON.stringify(user),
success: function(data){
console.log(data);
},
error: function(error){
console.log(error);
}
});
});
Following is my login controller class code
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public static User register(User user){
System.out.println("in register");
User register = null;
if(!validateUser(user.getEmail())){
System.out.println("calling new user");
register = loginDao.addNewUser(user);
System.out.println("returning user");
}
return register;
}
how shall I send complex user to my code? shall I say #Path("{user}") ?
HI You can send complex Object using Post method to your Rest API.
Below is the REST API that will accept the User JOSN object.
You can Follow more about how to post Complex Object here:http://entityclass.in/rest/jerseyClientGetXml.htm
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/StudentService")
public class StudentService {
#POST
#Path("/update")
#Consumes(MediaType.APPLICATION_JSON)
public Response consumeJOSN( User user ) {
User output = user.toString();
return Response.status(200).entity(output).build();
}
}
For this RestFull API i have written JAVA client
public class ClientJerseyPost {
public static void main(String[] args) {
try {
User user = new User();
user.setName("JON");
user.setAddress("Paris");
user.setId(5);
String resturl = "http://localhost:8080/RestJerseyClientXML/rest/StudentService/update";
Client client = Client.create();
WebResource webResource = client.resource(resturl);
ClientResponse response = webResource.accept("application/json")
.post(ClientResponse.class, student);
String output = response.getEntity(String.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
} catch (Exception e) {
}
}
}
I have Subscriber and Contact domain and a subscriber can have many contacts(one to many) in grails app. When I try to delete data from table contact it throws error like DBCExceptionReporter Cannot delete or update a parent row: a foreign key constraint fails (vprocure5.subscriber_contact, CONSTRAINTFKC5D3AF49E9F29F5FOREIGN KEY (contact_id) REFERENCEScontact(id)).
According to error message, I can not delete a parent row, but actually I am trying to delete contact data which are children of "Subscriber" domain. Here Subscriber should be parent and Contact should be child domain if I am not wrong.
Subscriber domain
static hasMany= [contacts: Contact ]
Contact domain
static belongsTo = [Subscriber ]
ContactController.grooby
package com.vproc.member
import org.springframework.dao.DataIntegrityViolationException
class ContactController {
def springSecurityService
def subscriberService
def imageUploadService
def searchableService
def autoCompleteService
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
List<Contact>contactsList = new ArrayList<Contact>();
loggedinSubscriber?.contacts.each { it ->
contactsList.add(it)
}
[contactInstanceList:contactsList , contactInstanceTotal: contactsList.size() ]
}
def create() {
[contactInstance: new Contact(params)]
}
def save() {
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
def ajaxDelete = {
def contactInstance = Contact.get( params.id );
contactInstance.tags.clear();
println "=========================="
if(contactInstance) {
try {
println "+++++++++++++++++++++++++"
contactInstance.delete(flush:true)
render "contact ${params.id} deleted"
}
catch(org.springframework.dao.DataIntegrityViolationException e) {
render "contact ${params.id} could not be deleted"
}
}
else {
flash.message = "contact not found with id ${params.id}"
render(action:list)
}
}
Contact.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.Tag;
import com.vproc.enquiry.ContactType;
import grails.converters.JSON;
class Contact {
String name
String phoneNumber
String emailAddress
Gender gender
String url
String note
byte[] image
String address
Date dateCreated
Date lastUpdated
ContactType contactType
Date birthday
static belongsTo = [Subscriber ]
static hasMany = [tags:Tag , shares: SharedContact]
static constraints = {
image nullable: true
phoneNumber nullable: true
url nullable :true
address nullable :true
gender nullable :true
note nullable :true
contactType nullable :true
birthday nullable :true
}
static mapping = {
tags cascade: "all-delete-orphan"
}
//static searchable = [only: ['name', 'emailAddress']]
static searchable = true
static scaffold = true
//static searchable = true
}
Subscriber.groovy
package com.vproc.member
import java.util.Date;
class Subscriber extends PartyRole{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
StatusEnum status
Date dateCreated
Date lastUpdated
List<Contact> contacts ;
static belongsTo = [ customer: Customer]
static hasMany = [scontacts: Contact]
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
SubscriberRole.findAllBySubscriber(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
Any idea how I can delete contact records here?
delete action in Contact controller
def ajaxDelete = {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
def contactInstance = Contact.get( params.id );
contactInstance.tags.clear();
loggedinSubscriber.removeFromContacts(contactInstance)
println "=========================="
if(contactInstance) {
try {
println "+++++++++++++++++++++++++"
contactInstance.delete(flush:true)
render "contact ${params.id} deleted"
}
catch(org.springframework.dao.DataIntegrityViolationException e) {
render "contact ${params.id} could not be deleted"
}
}
else {
flash.message = "contact not found with id ${params.id}"
render(action:list)
}
}
Because you've mapped the relationship like this:
static belongsTo = [Subscriber]
Grails has created a join table called subscriber_contact. You can see this in your error message:
delete or update a parent row: a foreign key constraint fails
(vprocure5.subscriber_contact, CONSTRAINTFKC5D3AF49E9F29F5FOREIGN
KEY (contact_id) REFERENCEScontact(id))
In this case, you would actually need to use the removeFrom method on Subscriber to delete the contact.
subscriberInstance.removeFromContacts(contactInstance)
Then, GORM will internally handle removing the row from the subscriber_contact table.
Optionally, you should be able to map your relationship using the map notation:
static belongsTo = [subscriber: Subscriber]
This should negate the need for Grails to create the join table and you should be able to delete the contact directly since it will just contain a FK to the subscriber table.
I created a grails app with Subscriber and Contact modeled the way you have them. I then wrote the following test, which passes:
#TestFor(Contact)
#Mock([Contact, Subscriber])
class ContactTests {
void setUp() {
def subscriber = new Subscriber(name: 's1')
def contact = new Contact(name: 'c1')
subscriber.addToContacts(contact)
subscriber.save()
}
void testDeleteContactFromSubscriber() {
assertEquals(Contact.list().size(), 1)
def dbSubscriber = Subscriber.findByName('s1')
def dbContact = Contact.findByName('c1')
dbSubscriber.removeFromContacts(dbContact)
dbContact.delete()
assertEquals(Contact.list().size(), 0)
}
}
I am trying to register a custom json marshaller like this
JSON.createNamedConfig("dynamic",{
def m = new CustomJSONSerializer()
JSON.registerObjectMarshaller(Idf, 1, { instance, converter -> m.marshalObject(instance, converter) })
})
and then using it like this
JSON.use("dynamic"){
render inventionList as JSON
}
but I am not sure if my custom serializer is being used because when I am debugging
control never goes to marshalObject function of my custom serializer
My custom serializer is as follows
import grails.converters.deep.JSON
import java.beans.PropertyDescriptor
import java.lang.reflect.Field
import java.lang.reflect.Method
import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException
import org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller
import org.codehaus.groovy.grails.web.json.JSONWriter
class CustomJSONSerializer extends GroovyBeanMarshaller{
public boolean supports(Object object) {
return object instanceof GroovyObject;
}
public void marshalObject(Object o, JSON json) throws ConverterException {
JSONWriter writer = json.getWriter();
println 'properties '+BeanUtils.getPropertyDescriptors(o.getClass())
for(PropertyDescriptor property:BeanUtils.getProperyDescriptors(o.getClass())){
println 'property '+property.getName()
}
try {
writer.object();
for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(o.getClass())) {
String name = property.getName();
Method readMethod = property.getReadMethod();
if (readMethod != null && !(name.equals("metaClass")) && readMethod.getName()!='getSpringSecurityService') {
Object value = readMethod.invoke(o, (Object[]) null);
writer.key(name);
json.convertAnother(value);
}
}
for (Field field : o.getClass().getDeclaredFields()) {
int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) && !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
writer.key(field.getName());
json.convertAnother(field.get(o));
}
}
writer.endObject();
}
catch (ConverterException ce) {
throw ce;
}
catch (Exception e) {
throw new ConverterException("Error converting Bean with class " + o.getClass().getName(), e);
}
}
}
Is it possible to debug the serializer? If not then how can I exclude a property from serialization? There's some property which throws exception during serialization.
this is what i do for custom JSON marshaling in the Bootstrap init closure:
def init = {servletContext ->
grailsApplication.domainClasses.each {domainClass ->
domainClass.metaClass.part = {m ->
def map = [:]
if (m.'include') {
m.'include'.each {
map[it] = delegate."${it}"
}
} else if (m.'except') {
m.'except'.addAll excludedProps
def props = domainClass.persistentProperties.findAll {
!(it.name in m.'except')
}
props.each {
map['id'] = delegate.id
map[it.name] = delegate."${it.name}"
}
}
return map
}
}
JSON.registerObjectMarshaller(Date) {
return it?.format("dd.MM.yyyy")
}
JSON.registerObjectMarshaller(User) {
def returnArray = [:]
returnArray['username'] = it.username
returnArray['userRealName'] = it.userRealName
returnArray['email'] = it.email
return returnArray
}
JSON.registerObjectMarshaller(Role) {
def returnArray = [:]
returnArray['authority'] = it.authority
return returnArray
}
JSON.registerObjectMarshaller(Person) {
return it.part(except: ['fieldX', 'fieldY'])
}}
you see that i have custom marshallers for the Date, Use, Person, and Role Class
I found this post while trying to find out a proper way for the marshaller registering. The biggest difference compared to Nils' answer is that this solution leaves BootStrap.groovy intact, which is nice.
http://compiledammit.com/2012/08/16/custom-json-marshalling-in-grails-done-right/
To customize Json serialization , the best practices is to use a grails plugin,such as the following :
http://grails.org/plugin/marshallers