How to perform Spring validation in MultiActionController?
Let's write the following one
public class Person {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And your MultiActionController
import static org.springframework.validation.ValidationUtils.*;
#Component
public class PersonController extends MultiActionController {
public PersonController() {
setMethodNameResolver(new InternalPathMethodNameResolver());
setValidators(new Validator[] {new Validator() {
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(Person.class);
}
public void validate(Object command, Errors errors) {
rejectIfEmpty(errors, "age", "", "Age is required");
rejectIfEmptyOrWhitespace(errors, "name", "", "Name is required");
}
}});
}
public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Person person) throws Exception {
// do something (save our Person object, for instance)
return new ModelAndView();
}
}
MultiActionController defines a property called validators where you should provide any Validator used by your MultiActionController. Here you can see a piece of code which is responsible for validating your Command object inside MultiActionController
ServletRequestDataBinder binder = ...
if (this.validators != null)
for (int i = 0; i < this.validators.length; i++) {
if (this.validators[i].supports(command.getClass())) {
ValidationUtils.invokeValidator(this.validators[i], command, binder.getBindingResult());
}
}
}
/**
* Notice closeNoCatch method
*/
binder.closeNoCatch();
closeNoCatch method says
Treats errors as fatal
So if your Validator returns any Error, closeNoCatch will throw a ServletRequestBindingException. But, you can catch it inside your MultiActionController method, as follows
public ModelAndView hanldeBindException(HttpServletRequest request, HttpServletResponse response, ServletRequestBindingException bindingException) {
// do what you want right here
BindException bindException = (BindException) bindingException.getRootCause();
return new ModelAndView("personValidatorView").addAllObjects(bindException.getModel());
}
In order to test, let's do the following one
#Test
public void failureValidation() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("POST");
request.setRequestURI("http://127.0.0.1:8080/myContext/person/add.html");
/**
* Empty values
*/
request.addParameter("name", "");
request.addParameter("age", "");
PersonController personController = new PersonController();
ModelAndView mav = personController.handleRequest(request, new MockHttpServletResponse());
BindingResult bindingResult = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "command");
/**
* Our Validator rejected 2 Error
*/
assertTrue(bindingResult.getErrorCount() == 2);
for (Object object : bindingResult.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
System.out.println(fieldError.getField());
}
}
}
Related
i have below resttempalte which invokes rest controller of another service..
#Override
public ResponseEntity<String> callRestAPI(APIReqDataMO apiReqDataMO) {
String apiURL = URIGenerator.getAPIURL(apiReqDataMO);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> request = new HttpEntity<>(apiReqDataMO.getRequestObject(), headers);
ResponseEntity<String> httpRes = restTemplate.postForEntity(apiURL, request, String.class);
return httpRes;
}
and in my service i have controller, which consumes above request..
#RequestMapping(value = "/targetService/createUser", method = RequestMethod.POST, consumes = "application/json")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("---------------------age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
System.out.println("error age greater than 0 ");
return "invalid user age";
} else if (userMO.getAge() == 0) {
return "invalid user age";
}
return "user added successfully";
}
when i try my test.. the age which i am pushing through rest template is not getting mapped..and i am getting age as 0 always in my system.out.. what could be wrong in my code... and is there anything missing from configuration perspective..
EDIT -
public class APIReqDataMO {
private String restAPIURL;
private Object[] pathParam;
private Object[] requestParam;
private String requestType;
private String paramType;
private Object requestObject;
public String getParamType() {
return paramType;
}
public void setParamType(String paramType) {
this.paramType = paramType;
}
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public Object getRequestObject() {
return requestObject;
}
public void setRequestObject(Object requestObject) {
this.requestObject = requestObject;
}
public String getRestAPIURL() {
return restAPIURL;
}
public void setRestAPIURL(String restAPIURL) {
this.restAPIURL = restAPIURL;
}
public Object[] getPathParam() {
return pathParam;
}
public void setPathParam(Object[] pathParam) {
this.pathParam = pathParam;
}
public Object[] getRequestParam() {
return requestParam;
}
public void setRequestParam(Object[] requestParam) {
this.requestParam = requestParam;
}
}
controller
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("--------------------- age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
// return ResponseEntity.ok("Hello World!");
} else if (userMO.getAge() == 0) {
System.out.println(" it is else block");
// return ResponseEntity.badRequest().build();
}
// return ResponseEntity.ok("user added successfully!");
return "user added successfully";
}
usermo
public class UserMO {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Issue
There is an issue in API implementation. You are creating POST API and when the user will invoke this API by passing UserMO in the request body then mapping won't happen because the #RequestBody annotation is missing.
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(UserMO userMO) {
System.out.println("--------------------- age is -------------------------" + userMO.getAge());
if (userMO.getAge() > 0) {
// return ResponseEntity.ok("Hello World!");
} else if (userMO.getAge() == 0) {
System.out.println(" it is else block");
// return ResponseEntity.badRequest().build();
}
// return ResponseEntity.ok("user added successfully!");
return "user added successfully";
}
Solution
If you are using #RestController annotation on top of the controller class then add #RequestBody annotation before UserMO userMO and try again.
Like this
#PostMapping("/targetService/createUser")
public String fuzzerServiceAge(#RequestBody UserMO userMO) {
//logic
}
if you are using #Controller annotation on top of the controller class then add #ResponseBody annotation on top of method fuzzerServiceAge() and #RequestBody annotation before UserMO userMO and try again.
Like this
#PostMapping("/targetService/createUser")
#ResponseBody
public String fuzzerServiceAge(#RequestBody UserMO userMO) {
//logic
}
I want change data after #RestController class in Spring
I need to change the fields data based on the specified language.
example:
enum:
public enum Gender {
WOMAN, MAN, OTHER
}
the controller:
#RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public User get(#PathVariable Long id) throws Exception {
log.debug("Entering get( id={} )", id);
User user = null;
try {
user = UserService.get(id);
} catch (Exception e) {
log.debug("Error occurred in get().", e);
throw e;
}
return user;
}
this output:
{
fisrtName: 'john',
lastName: 'doe',
gender: 'man'
}
change to this output:
{
fisrtName: 'john',
lastName: 'doe',
gender: 'homme'
}
I assume user.gender is a enum. Then you could add a custom Serializer and Deserializer to your JSON Mapper (hopefully Jackson).
#JsonComponent
public class TranslatedGenderJsonComponent {
public static class TranslatedGenderSerializer extends StdSerializer<Gender> {
public TranslatedGenderSerializer () {
super(Gender.class);
}
public void serialize(
Gender gender, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
String translatedGender = myTranslateFunction(gender);
generator.writeString(translatedGender );
}
}
public static class TranslatedGenderDeserializer extends StdDeserializer<Gender> {
public TranslatedGenderDeserializer () {
super(Gender.class);
}
public Gender deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonToken currentToken = jp.getCurrentToken();
if (currentToken.equals(JsonToken.VALUE_STRING)) {
String text jp.getText().trim();
Gender gender = myInverseTranslateFunction(text);
return gender;
} else if (currentToken.equals(JsonToken.VALUE_NULL)) {
return getNullValue();
} else {
throw ctxt.mappingException(Gender.class);
}
}
}
}
This code is not tested, it is just written in the browser! (I am quite unsure with the deserializer/parser code.) But I hope it will guide you to a solution.
I changed code:
the controller:
#Autowired
GlobalMassengerAdvice globalMassenger;
#RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public User get(#PathVariable Long id) throws Exception {
log.debug("Entering get( id={} )", id);
User user = null;
try {
user = userService.get(id);
String value = globalMassenger.getMessage(user.getGender().name());
user.setGender( value );
} catch (Exception e) {
log.debug("Error occurred in get().", e);
throw e;
}
return user;
}
I add new Class (GlobalMassengerAdvice):
#ControllerAdvice
public class GlobalMassengerAdvice {
#Autowired
private MessageSource messageSource;
public String getMessage(final String messageKey, final Object... messageParameters) {
Locale locale = LocaleContextHolder.getLocale();
String result = null;
try {
result = messageSource.getMessage(messageKey, messageParameters, locale);
} catch (NoSuchMessageException e) {
result = messageKey;
}
return result;
}
}
I Wanted to create normal spring application (not spring boot or spring mvc) which uses Jakarta Bean Validation framework
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>7.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<version>4.0.0</version>
</dependency>
Tried to use above dependency but unable perform method/constructor argument validation using #NotNull #NotBlank etc.
Example
public TestConstructor(#NotNull #NotBlank final String param1, #NotNull #NotBlank final String param2, #NotNull #NotBlank final String param3) {
...
...
}
...
...
public void testMethod(#NotNull #NotBlank final String param1) {
...
}
I created the below bean and was only able to validate objects manually
#Bean
public Validator validator() {
return Validation.byProvider(HibernateValidator.class).configure().buildValidatorFactory().getValidator();
}
I wanted to perform auto validation of arguments and objects using jakarta bean validation framework (not with javax validation)
I'm faced with this issue too. So i just copied required parts of Spring framework and create my own ValidatorBean with B&W, but actually with only validation.
#Bean(name = "mvcValidator")
public JakartaValidator validatorFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
Validator validator = Validation.byDefaultProvider()
.configure()
.messageInterpolator(new ParameterMessageInterpolator())
.constraintValidatorFactory(new JakartaConstraintValidatorFactory(autowireCapableBeanFactory))
.buildValidatorFactory().getValidator();
return new JakartaValidator(validator);
}
public class JakartaConstraintValidatorFactory implements ConstraintValidatorFactory {
private final AutowireCapableBeanFactory autowireCapableBeanFactory;
#Autowired
public JakartaConstraintValidatorFactory(AutowireCapableBeanFactory autowireCapableBeanFactory) {
this.autowireCapableBeanFactory = autowireCapableBeanFactory;
}
#Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
return autowireCapableBeanFactory.createBean(key);
}
#Override
public void releaseInstance(ConstraintValidator<?, ?> instance) {
autowireCapableBeanFactory.destroyBean(instance);
}
}
public class JakartaValidator implements Validator {
private static final Set<String> internalAnnotationAttributes = new HashSet<>(4);
static {
internalAnnotationAttributes.add("message");
internalAnnotationAttributes.add("groups");
internalAnnotationAttributes.add("payload");
}
private final jakarta.validation.Validator validator;
public JakartaValidator(jakarta.validation.Validator validator) {
this.validator = validator;
}
public void init() {
}
#Override
public boolean supports(Class<?> clazz) {
return true;
}
#Override
public void validate(Object target, Errors errors) {
processConstraintViolations(validator.validate(target), errors);
}
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
for (ConstraintViolation<Object> violation : violations) {
String field = determineField(violation);
FieldError fieldError = errors.getFieldError(field);
if (fieldError == null || !fieldError.isBindingFailure()) {
try {
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
String errorCode = determineErrorCode(cd);
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, cd);
if (errors instanceof BindingResult) {
// Can do custom FieldError registration with invalid value from ConstraintViolation,
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
BindingResult bindingResult = (BindingResult) errors;
String nestedField = bindingResult.getNestedPath() + field;
if (nestedField.isEmpty()) {
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode);
ObjectError error = new ViolationObjectError(
errors.getObjectName(), errorCodes, errorArgs, violation, this);
bindingResult.addError(error);
} else {
Object rejectedValue = getRejectedValue(field, violation, bindingResult);
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
FieldError error = new ViolationFieldError(errors.getObjectName(), nestedField,
rejectedValue, errorCodes, errorArgs, violation, this);
bindingResult.addError(error);
}
} else {
// got no BindingResult - can only do standard rejectValue call
// with automatic extraction of the current field value
errors.rejectValue(field, errorCode, errorArgs, violation.getMessage());
}
} catch (NotReadablePropertyException ex) {
throw new IllegalStateException("JSR-303 validated property '" + field +
"' does not have a corresponding accessor for Spring data binding - " +
"check your DataBinder's configuration (bean property versus direct field access)", ex);
}
}
}
}
#Nullable
protected Object getRejectedValue(String field, ConstraintViolation<Object> violation, BindingResult bindingResult) {
Object invalidValue = violation.getInvalidValue();
if (field != null && !field.isEmpty() && !field.contains("[]") &&
(invalidValue == violation.getLeafBean() || field.contains("[") || field.contains("."))) {
// Possibly a bean constraint with property path: retrieve the actual property value.
// However, explicitly avoid this for "address[]" style paths that we can't handle.
invalidValue = bindingResult.getRawFieldValue(field);
}
return invalidValue;
}
protected String determineField(ConstraintViolation<Object> violation) {
Path path = violation.getPropertyPath();
StringBuilder sb = new StringBuilder();
boolean first = true;
for (Path.Node node : path) {
if (node.isInIterable()) {
sb.append('[');
Object index = node.getIndex();
if (index == null) {
index = node.getKey();
}
if (index != null) {
sb.append(index);
}
sb.append(']');
}
String name = node.getName();
if (name != null && node.getKind() == ElementKind.PROPERTY && !name.startsWith("<")) {
if (!first) {
sb.append('.');
}
first = false;
sb.append(name);
}
}
return sb.toString();
}
protected String determineErrorCode(ConstraintDescriptor<?> descriptor) {
return descriptor.getAnnotation().annotationType().getSimpleName();
}
protected Object[] getArgumentsForConstraint(String objectName, String field, ConstraintDescriptor<?> descriptor) {
List<Object> arguments = new ArrayList<>();
arguments.add(getResolvableField(objectName, field));
// Using a TreeMap for alphabetical ordering of attribute names
Map<String, Object> attributesToExpose = new TreeMap<>();
descriptor.getAttributes().forEach((attributeName, attributeValue) -> {
if (!internalAnnotationAttributes.contains(attributeName)) {
if (attributeValue instanceof String) {
attributeValue = new ResolvableAttribute(attributeValue.toString());
}
attributesToExpose.put(attributeName, attributeValue);
}
});
arguments.addAll(attributesToExpose.values());
return arguments.toArray();
}
protected MessageSourceResolvable getResolvableField(String objectName, String field) {
String[] codes = {objectName + Errors.NESTED_PATH_SEPARATOR + field, field};
return new DefaultMessageSourceResolvable(codes, field);
}
protected boolean requiresMessageFormat(ConstraintViolation<?> violation) {
return containsSpringStylePlaceholder(violation.getMessage());
}
private static boolean containsSpringStylePlaceholder(#Nullable String message) {
return (message != null && message.contains("{0}"));
}
private static class ResolvableAttribute implements MessageSourceResolvable, Serializable {
private final String resolvableString;
public ResolvableAttribute(String resolvableString) {
this.resolvableString = resolvableString;
}
#Override
public String[] getCodes() {
return new String[]{this.resolvableString};
}
#Override
#Nullable
public Object[] getArguments() {
return null;
}
#Override
public String getDefaultMessage() {
return this.resolvableString;
}
#Override
public String toString() {
return this.resolvableString;
}
}
private static class ViolationObjectError extends ObjectError implements Serializable {
#Nullable
private final transient JakartaValidator adapter;
#Nullable
private final transient ConstraintViolation<?> violation;
public ViolationObjectError(String objectName, String[] codes, Object[] arguments,
ConstraintViolation<?> violation, JakartaValidator adapter) {
super(objectName, codes, arguments, violation.getMessage());
this.adapter = adapter;
this.violation = violation;
wrap(violation);
}
#Override
public boolean shouldRenderDefaultMessage() {
return (this.adapter != null && this.violation != null ?
this.adapter.requiresMessageFormat(this.violation) :
containsSpringStylePlaceholder(getDefaultMessage()));
}
}
private static class ViolationFieldError extends FieldError implements Serializable {
#Nullable
private final transient JakartaValidator adapter;
#Nullable
private final transient ConstraintViolation<?> violation;
public ViolationFieldError(String objectName, String field, #Nullable Object rejectedValue, String[] codes,
Object[] arguments, ConstraintViolation<?> violation, JakartaValidator adapter) {
super(objectName, field, rejectedValue, false, codes, arguments, violation.getMessage());
this.adapter = adapter;
this.violation = violation;
wrap(violation);
}
#Override
public boolean shouldRenderDefaultMessage() {
return (this.adapter != null && this.violation != null ?
this.adapter.requiresMessageFormat(this.violation) :
containsSpringStylePlaceholder(getDefaultMessage()));
}
}
}
I have a doubt about how to pass more data to throw an exception, I want to pass more data at the time of launching it, to put that data in the service response ..
I have an exception handler class labeled #ControllerAdvice in spring, but I don't know the best way to pass the data.
This is the code I have
throw new OcspException("Exception OCSP");
public class OcspException extends RuntimeException {
private static final long serialVersionUID = 1L;
public OcspException(String businessMessage) {
super(businessMessage);
}
public OcspException(String businessMessage, Throwable throwable) {
super(businessMessage, throwable);
}
}
#ExceptionHandler(OcspException.class)
public ResponseEntity<Object> exception(OcspException exception,HttpServletRequest request) {
ResponseException response = new ResponseException();
response.setCode("404");
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
I have the idea to do it, but I don't know if it is a good practice ... in the OcspException class to create attributes with their setter and getters, and create the constructor that receives this data, to then extract the data in exception controller
throw new OcspException("Exception OCSP","Hello");
public class OcspException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String m;
public OcspException(String businessMessage) {
super(businessMessage);
}
public OcspException(String businessMessage, Throwable throwable) {
super(businessMessage, throwable);
}
public OcspException(String businessMessage, String message) {
super(businessMessage);
setM(message);
}
public String getM() {
return m;
}
public void setM(String m) {
this.m = m;
}
}
#ExceptionHandler(OcspException.class)
public ResponseEntity<Object> exception(OcspException exception,HttpServletRequest request) {
ResponseException response = new ResponseException();
response.setCode("404");
response.setDetails(exception.getM() );
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
Try making an model called ErrorDetails which will hold a timestamp, message, and details.
It may look like this:
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class ErrorDetails {
private LocalDateTime timeStamp;
private String message;
private String details;
}
Here's a sample of what my custom exceptions usually look like:
#Data
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class OrderNotFoundException extends RuntimeException {
private final String message;
public OrderNotFoundException(String message) {
super(message);
this.message = message;
}
}
Then for the #ExceptionHandler:
#ExceptionHandler(OrderNotFoundException.class)
public ResponseEntity<ErrorDetails>
orderNotFoundException(OrderNotFoundException ex, WebRequest request) {
ErrorDetails errorDetails = ErrorDetails.builder()
.timeStamp(LocalDateTime.now())
.message(ex.getMessage())
.details(request.getDescription(false))
.build();
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
The error response for an order not found ends up being this:
{
"timeStamp": "2019-10-07T21:31:37.186",
"message": "Order with id 70 was not found.",
"details": "uri=/api/v1/order"
}
This way you can add whatever extra details in the ErrorDetails object. I hope that helps!
Im new using this front end framework application...
I recently started to work with smartgwt and i'm bulding a new application with a Spring MVC integration.
I'm using a ListGrid with a RestDataSource (Consume the Rest service with mvc:annotation-driven for plain JSON)
I can see that the servaice gets consuming properly perhaps my grid is never shown with the data in it.
Can someone help me here ?
Here's my ListGrid class
public class ListGrid extends com.smartgwt.client.widgets.grid.ListGrid {
private final SpringJSONDataSource springJSONDataSource;
public ListGrid(List<DataSourceField> fields) {
this(new PatientDataSource(fields));
}
public ListGrid(SpringJSONDataSource springJSONDataSource) {
this.springJSONDataSource = springJSONDataSource;
init();
}
private void init() {
setAutoFetchData(true);
setAlternateRecordStyles(true);
setEmptyCellValue("???");
setDataPageSize(50);
setDataSource(springJSONDataSource);
}
}
Now there's the DataSource implmentation
public abstract class SpringJSONDataSource extends RestDataSource {
protected final HTTPMethod httpMethod;
public SpringJSONDataSource(List<DataSourceField> fields) {
this(fields, HTTPMethod.POST);
}
public SpringJSONDataSource(List<DataSourceField> fields, HTTPMethod httpMethod) {
this.httpMethod = httpMethod;
setDataFormat(DSDataFormat.JSON);
addDataSourceFields(fields);
setOperationBindings(getFetch());
addURLs();
}
private void addURLs() {
if(getUpdateDataURL() != null)
setUpdateDataURL(getUpdateDataURL());
if(getRemoveDataURL() != null)
setRemoveDataURL(getRemoveDataURL());
if(getAddDataURL() != null)
setAddDataURL(getAddDataURL());
if(getFetchDataURL() != null)
setFetchDataURL(getFetchDataURL());
}
private void addDataSourceFields(List<DataSourceField> fields) {
for (DataSourceField dataSourceField : fields) {
addField(dataSourceField);
}
}
protected abstract OperationBinding getFetch();
protected abstract OperationBinding getRemove();
protected abstract OperationBinding getAdd();
protected abstract OperationBinding getUpdate();
public abstract String getUpdateDataURL();
public abstract String getRemoveDataURL();
public abstract String getAddDataURL();
public abstract String getFetchDataURL();
}
The class PatientDataSource that extends SpringJSONDataSource
public class PatientDataSource extends SpringJSONDataSource {
public PatientDataSource(List<DataSourceField> fields) {
super(fields);
setPrettyPrintJSON(true);
}
#Override
protected OperationBinding getFetch() {
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
DSRequest fetchProps = new DSRequest();
fetchProps.setHttpMethod(httpMethod.toString());
fetch.setRequestProperties(fetchProps);
return fetch;
}
#Override
public String getFetchDataURL() {
return "/spring/fetchPatients";
}
#Override
protected OperationBinding getRemove() {
return null;
}
#Override
public String getRemoveDataURL() {
return null;
}
#Override
protected OperationBinding getAdd() {
return null;
}
#Override
public String getAddDataURL() {
return null;
}
#Override
protected OperationBinding getUpdate() {
return null;
}
#Override
public String getUpdateDataURL() {
return null;
}
}
My spring controller PatientControler
#Controller
public class PatienController {
Logger logger = Logger.getLogger(PatienController.class);
#Autowired
private PatientServices patientServices;
#RequestMapping(value = "/patientTest", method = RequestMethod.GET)
#ResponseBody
public Object getTest()
{
return patientServices.getAllPatients();
}
#RequestMapping(value = "/fetchPatients", method = RequestMethod.POST)
#ResponseBody
public Object getAllPatients()
{
return patientServices.getAllPatients();
}
}
PatientServiceImpl
public class PatientServicesImpl implements PatientServices {
public List<Patient> getAllPatients() {
List<Patient> patients = new ArrayList<Patient>();
Patient patient;
for(int i = 0 ; i < 500 ; i++){
patient = new Patient();
patient.setDateOfBirth(new Date());
patient.setFirstName("Joe");
patient.setMiddleName("Moe");
patient.setLastName("Blow");
patient.setLastConsultation(new Date());
patient.setSex(Sex.M);
patients.add(patient);
}
return patients;
}
}
*Im Really stuck right now i've been looking for all type of answers .... but so far nothing worked when i tried to override the transformResponse from my RestDataSource impentation the parameter "data" as an OBJECT, returns me an array [object Object],[object Object],[object Object],[object Object],[object Object] *
The Data which is transferred from the RestDataSource has a specific format which is described in the JavaDoc of the RestDataSource
Your server must understand the request and send back a valid response.
At the moment your example doesn't seem to honour the contract.
To debug the traffic send to and from your server you can use the SmartClient-Console. You can open it by a browser bookmark like this:
javascript:isc.showConsole()
Of cause you need to deploy this console by adding the following module to your gwt.xml
<inherits name="com.smartclient.tools.SmartClientTools"/>
Now go to the RPC Tab and check Track-RPCs