I'm working with Spring Boot 2.4.5, MyBatis 3.5.6 and Java 8. When trying to return a String from a @RestController
, an obscure error shows up in the returned HttpErrorResponse
.
The method tries to obtain the value via MyBatis, i.e., a method in a DAO object that acts as a @Mapper
.
My controller method:
@RestController
@RequestMapping("/api/myAPI")
public class MyController{
@Resource
private MyService service;
@GetMapping(value = "myString")
public String getBillingCompany() {
return this.service.getDAO().getMyString();
}
}
My DAO:
@Repository
@Mapper
public interface MyDAO{
String getMyString();
}
...and the MyBatis mapper:
<mapper namespace="com.package.MyDAO">
<select id="getMyString" resultType="String">
SELECT 'My desired result' FROM A_TABLE
</select>
...
</mapper>
The HttpErrorResponse:
HttpErrorResponse: {
"headers": {
"normalizedNames": {},
"lazyUpdate": null
},
"status": 200,
"statusText": "OK",
"url": "http://localhost:4200/api/myAPI/myString",
"ok": false,
"name": "HttpErrorResponse",
"message": "Http failure during parsing for http://localhost:4200/api/myAPI/myString",
"error": {
"error": { SyntaxError: Unexpected number in JSON at position 2
at JSON.parse (<anonymous>)
at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:18158:51)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:21266:35)
at Object.onInvokeTask (http://localhost:4200/vendor.js:74037:33)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:21265:40)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (http://localhost:4200/polyfills.js:21033:51)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:21348:38)
at invokeTask (http://localhost:4200/polyfills.js:22516:18)
at XMLHttpRequest.globalZoneAwareCallback (http://localhost:4200/polyfills.js:22553:25)
},
"text": "My desired result"
}
}
Nonetheless, if I ask the controller and the DAO methods to return an int
, it all works flawlessly.
Due to this, I suspected that the issue has to do with non-primitive types "namespacing", so I've tried to set a typeAlias
in the MyBatis configuration, to no avail:
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="java.lang.String" alias="String"/>
</typeAliases>
</configuration>
Anyways, I'm under the impression that both MyBatis and Spring should be already smart enough to know what a String
is. I've successfully returned collections of objects (Map
s and List
s) and POJOs in the past.
Any ideas on what I'm lacking or not seeing? Thanks in advance.
Edit:
The only thing that has worked for me so far is similar to what @emeraldjava proposed. I've built a wrapper upon an existing one in a dependency, fetching the data
in my Front:
@RestController
@RequestMapping("/api/myAPI")
public class MyController{
@Resource
private MyService service;
@GetMapping(value = "myString")
public Result<String> getBillingCompany() {
return new Result<>(this.service.getDAO().getMyString());
}
}
public class Result<T> extends ServiceResult {
public Result(T data) {
this.setData(data);
}
}
The already existing wrapper in a dependency:
public class ServiceResult {
private Object data;
...
public void setData(Object data) {
this.data = data;
}
public Object getData() {
return this.data;
}
}
I'd suggest you update your Controller method to a ResponseEntity which wraps the string.
@RestController
@RequestMapping("/api/myAPI")
public class MyController{
@Resource
private MyService service;
@GetMapping(value = "myString")
public ResponseEntity getBillingCompany() {
return new ResponseEntity<Object>(this.service.getDAO().getMyString(), HttpStatus.OK);
}
}