I get an error message when i try to parse an XML response using REST assured - rest-assured

Iam using this simple function to get and print out the value at an XML response:
#Test
void validateXMLResponse() {
String book = RestAssured.given().when()
.get("https://chercher.tech/sample/api/books.xml")
.then().extract().path("bookstore.book.title");
System.out.println(book);
}
But iam getting this error in the console:
java.lang.ClassCastException: class io.restassured.internal.path.xml.NodeChildrenImpl cannot be cast to class java.lang.String (io.restassured.internal.path.xml.NodeChildrenImpl is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')

Since you have more than book node in your xml, you should use corresponding index to define which book's title you want to get. Like this: "bookstore.book[0].title". Or iterate through index to get all the books titles.
#Test
public void validateXMLResponse() {
String book = RestAssured.given().when()
.get("https://chercher.tech/sample/api/books.xml")
.then().extract().body().path("bookstore.book[0].title");
System.out.println(book);
}

Related

grails #BindUsing command Object

I am using grails 2.5.5 and the problem is when I'm using a command Object, I want to change the format of the data I get with the #BindUsing annotation.
#Validatable
class FooCommand extends BarCommand{
#BindUsing({obj, source -> return source['foo'].collect{it['id']}})
List<Long> foo
static constraints = {foo(nullable:true)}
}
the BindUsing closure never gets executed. What is the problem and how to solve?
JSONData = {"foo":[
{'id':5},
{'id':4}
]
}
FooCommand fooCommand = FooCommand(JSONData)
fooCommand.validate()
EDIT:
To be clear: the problem is that the data change from format,from list of maps, to just a list of longs. Is there a way to do this with the BindUsing or will i just have to do it in the controller each time?

Null Pointer exception when calling service method from controller

I have a method in service class which has to be called from the controller. Both the controller and the service class codes are as below.
folder grails-app/services, file FileFactoryService.groovy
package edu.rev.document
import grails.transaction.Transactional
Class FileFactoryService{
Document document = new Document() // Domain object
def build(byte[] fileArray){
String str = new String(fileArray, "UTF-8") // UTF encoding as invoice may contain negative values
String[] lines = str.split("\\r?\\n")
document.version = lines[0].substring(0,1)
document.name = lines[1].substring(0,25)
}
return document.properties.collect()
}
Controller Code: folder: grails-app/controllers, file: FileController.groovy
package edu.rev.document
Class FileController{
def fileFactoryService
def save(){
def file = request.getFile('file')
if(file.empty) {
flash.message = "File cannot be empty"
} else {
def myList = fileService.build(file.getBytes())
}
}
The error thrown is
NullPointer exception when processing [POST]/../save
Cannot invoke method build() on NULL object
Can you please point me to the mistake I might be committing? Let me know if you need any other information
EDIT:This is the code. Just a heads up, the same logic when taken out of the service and implemented in the controller itself works perfectly alright. One more thing, when I use the "." operator inside the service (say document.), it doesnt show may any auto complete options like document.name.
Posting all of your code helps in finding the error. This line in your controller class
def myList = fileService.build(file.getBytes())
should be
def myList = fileFactoryService.build(file.getBytes())
In your controller class, you declared the service as :
def fileService
But the name of your service class is :
Class FileFactoryService
For Grails dependency injection to work, you need to name the variable like your class name :
def fileFactoryService
Then this should work.

MongoDB Collection Access

I'm using MongoDB exclusively with a Grails REST app and the domain shown below. This respond call fails:
#Secured(['permitAll'])
def index() {
respond Person.list()
}
with the error
ERROR errors.GrailsExceptionResolver - IllegalAccessException occurred when processing request: [GET] /teesheet/person
Class org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller can not access a member of class java.util.Collections$UnmodifiableCollection with modifiers "public". Stacktrace follows:
Message: Class org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller can not access a member of class java.util.Collections$UnmodifiableCollection with modifiers "public"
Attempting to convert the collection to JSON also fails with the same error.
def personList = Person.list() as JSON
The low level API works.
package com.tworks.teesheet
import grails.rest.Resource
class Person {
String name
String firstName
String lastName
String email
User userPerson
TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles")
Date dateCreated = new Date()
Date dateModified = new Date()
}
Assuming you're using Mongo for Grails plugin, you need #Entity for domain classes...
import grails.persistence.Entity
#Entity
class Person {
static mapWith = "mongo"
String name
String firstName
String lastName
String email
}
I added mapWith="mongo" since I wasn't sure if you're using the hibernate plugin alongside the mongo plugin; if you're not, remove hibernate, otherwise, it may interfere.
I'm currently using the low level calls to iterate using the cursor but it seems like the respond Person.list() should work. This code is working:
def cursor = Person.collection.find()
def items = []
try {
while (cursor.hasNext()) {
items << com.mongodb.util.JSON.serialize(cursor.next())
}
} finally {
cursor.close()
}
log.info("items: ${items}")
render items

grails: findallbyidinlist method

In my grails project, I've used the method Object.findAllByIdInList(), passing a list as parameter.
The code used is the following:
def allSelectedIds = ReceiptItem.findAllByIdInList(par)
In which the ReceiptItem is a domain class defined as follows:
class Receipt {
double totalAmount;
Date releaseDate;
int vatPercentage;
int discount;
Boolean isPayed;
Boolean isInvoice;
static belongsTo = [patient:Patient]
static hasMany = [receiptItems:ReceiptItem]
static constraints = {
receiptItems(blank: false)
patient(blank: false)
totalAmount(blank: false)
vatPercentage(blank: false, nullable: false)
}
}
and par is the list of ids defined as follows:
def par = params.list("receiptItemsSelected")
receiptItemsSelected is defined in the gsp page into the remoteFunction() as follows:
params: '\'receiptItemsSelected=\' + jQuery(this).val()'
The problem is that the line above throws the following exception:
java.lang.String cannot be cast to java.lang.Long. Stacktrace follows:
Message: java.lang.String cannot be cast to java.lang.Long
I don't understand why it is throwing this exception.
Thanks for your help
Probably list par has ids as String. Generally id for domain objects is stored as Long. Try this instead
ReceiptItem.findAllByIdInList(par*.toLong())
*Also make sure that id represented as string isNumber().
assert !'C'.isNumber()
assert '4'.isNumber()

Displaying Grails Field Errors

Does anybody know how I could get the fieldError to print out in the example below.
for each item with an error, I would like to print custom error messages that I have defined in the messages.properties file
at the moment all this does is print the default error codes
item.errors?.allErrors?.each{
println it.toString()
}
I have seen other examples where you can lookup an error code for a field e.g.
it.getFieldError('title').code
but I would like to convert the default message into my new error message and print that.
You need access to the messageSource bean, e.g. with
def messageSource
in your controller or service. Then you can access the messages with
def locale = Locale.getDefault()
for (fieldErrors in bean.errors) {
for (error in fieldErrors.allErrors) {
String message = messageSource.getMessage(error, locale)
}
}
A somewhat simplier solution with a better performance would be;
MessageSource messageSource //Inject the messageSource class
e.errors.allErrors.each {
String message = messageSource.getMessage(it, Locale.default)
}
OR
If you want to deal only with field errors:
e.errors.fieldErrors.each {
String message = messageSource.getMessage("modified.invalid.validator.message", [it.field, 'message'] as Object[], Locale.default))
}
Where modified.invalid.validator.message is the local string in your messages.properties. In this particular example, this message reads something like...
modified.invalid.validator.message=Property [{0}] of [{1}] does not pass validation

Resources