mock.method call returns null after stubbing - junit

I am trying to test using Mockito
my class under test is
#Service
public class DynatraceAPIServiceImpl implements DynatraceAPIService {
private String apiUrl = "someurl";
private String apiToken = "sometoken";
#Override
public CreateCustomMetricResponse createCustomMetric(CreateCustomMetricRequest request) throws MonitoringException {
logger.info("Inside create custom metric");
if (request == null) {
logger.error("create metric request is null");
throw new MonitoringException("Create metric request is null");
}
String metricId = DynatraceConstants.METRIC_ID;
String displayName = request.getDisplayName();
CreateCustomMetricResponse response = httpUtils.postCustomMetric(apiUrl + "/v1/timeseries/" + metricId, apiToken, request);
if (response == null) {
logger.error("Error in creating custom metric with name : " + displayName);
throw new MonitoringException("Error in creating custom metric with name : " + displayName);
}
logger.info("Custom metric : " + displayName + " is created successfully.");
return response;
}
}
and my Test class is :
#RunWith(MockitoJUnitRunner.class)
public class DynatraceAPIServiceImplTest {
#InjectMocks
DynatraceAPIServiceImpl dynatraceAPIServiceImpl;
#Mock
DynatraceHttpUtils httpUtilsMock;
#Mock
DynatraceMonitoringUtils monitoringUtilsMock;
#Test(expected = MonitoringException.class)
public void createCustomMetricGetsNonNullResponse() throws MonitoringException {
CreateCustomMetricRequest mockRequest = CreateCustomMetricRequest.builder()
.displayName(DISPLAY_NAME)
.types(new String[] {"test-type"})
.build();
CreateCustomMetricResponse response = CreateCustomMetricResponse.builder()
.displayName(DISPLAY_NAME)
.types(new String[] {"test-type"})
.timeseriesId(TIMESERIES_ID)
.build();
boolean val = true;
when(monitoringUtilsMock.isValidMetricIdValue(anyString())).thenReturn(val);
when(httpUtilsMock.postCustomMetric(API_URL + "/v1/timeseries/" + METRIC_ID, API_TOKEN, mockRequest)).thenReturn(response);
CreateCustomMetricResponse actualRespnose = dynatraceAPIServiceImpl.createCustomMetric(mockRequest);
//verify(httpUtilsMock, times(1)).postCustomMetric(anyString(), anyString(), any(CreateCustomMetricRequest.class));
//assertEquals(actualRespnose.getDisplayName(), DISPLAY_NAME);
}
}
Here, when I execute the tests, it always end up having the response value to be null in line
CreateCustomMetricResponse response = httpUtils.postCustomMetric(apiUrl + "/v1/timeseries/" + metricId, apiToken, request);
Even if I have used when() statement to return response as I have created, it is returning null.
Really appreciate if someone can let me know what is wrong here. Thanks.

That normally happens when the params your production code uses differ from the ones that you stubbed the call with, an easy way to find out is to write the test like this
when(httpUtilsMock.postCustomMetric(any(), any(), any())).thenReturn(response);
CreateCustomMetricResponse actualRespnose = dynatraceAPIServiceImpl.createCustomMetric(mockRequest);
verify(httpUtilsMock).postCustomMetric(API_URL + "/v1/timeseries/" + METRIC_ID, API_TOKEN, mockRequest);
If you do that, you'll get a nicer error showing the difference between what your code did and what you verified it for
A better approach in general is to use 'strict stubs' so if your code does anything different to what you stubbed the mock for you'll get a nice error telling you what, where and why

Related

jax-rs exception mapper implementation issues

I'm trying to implement a web service using Jersey 2.22.2 and Jetty 9.1.1.v20140108 with exception mapping. The following class represents an Exception class with Mapper implemented.
#Provider
public class NotFoundException extends Exception implements ExceptionMapper<NotFoundException> {
private static final long serialVersionUID = 1L;
public NotFoundException() {
}
public NotFoundException(String s) {
super(s);
}
#Context
private UriInfo uriInfo;
#Override
public Response toResponse(NotFoundException e) {
Status status = Status.NOT_FOUND;
ErrorWrapper errorWrapper = new ErrorWrapper();
errorWrapper.setStatusCode(status.getStatusCode());
errorWrapper.setTitle(status.getReasonPhrase());
errorWrapper.setErrorMessage("The resource you're looking for cannot be found.");
errorWrapper.setApiPath(uriInfo.getAbsolutePath().getPath());
return Response.status(status).entity(errorWrapper).type(MediaType.APPLICATION_JSON).build();
}
}
To test, whether this is working or not, I created an endpoint that simply throws the above exception, like this:
#GET
#Path("test")
#Produces(MediaType.APPLICATION_JSON)
public Response test() throws NotFoundException {
throw new NotFoundException();
}
Calling this endpoint returns a JSON, like this:
{
"statusCode": 404,
"title": "Not Found",
"errorMessage": "The resource you're looking for cannot be found.",
"apiPath": "/users/test"
}
From that, I kinda safely assumed that the exception mapping is working.
Now, what I'm trying to do is to throw this exception, if DAO method returns a null object, for example when trying to fetch a database row that doesn't exist yet. Following are my implementation attempts:
DAO:
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id)
.fetchOne()
.into(User.class);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
Service:
public User getUserById(Integer id) throws NotFoundException {
return userDao.getUserById(id);
}
Resource:
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserById(#PathParam("id") Integer id) throws NotFoundException {
User user = new UserService().getUserById(id);
return Response.ok(user).build();
}
But, when I call the endpoint using an id that doesn't exist yet(2), and get a NullPointerException, I'm still getting a HTTP 500 Request Failed from Jetty, instead of 404 from NotFoundException, like this:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
<title>Error 500 </title>
</head>
<body>
<h2>HTTP ERROR: 500</h2>
<p>Problem accessing /users/2. Reason:
<pre> Request failed.</pre>
</p>
<hr /><i><small>Powered by Jetty://</small></i>
</body>
</html>
Could really use some help with this.
You are not throwing the NotFoundException.
Your code is throwing a NullPointerException.
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id)
//The NullPointerException is coming from the following line
.fetchOne()
.into(User.class);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
You need to change your code to something like this:
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
user.fetchOne()
.into(User.class);
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
#galusben's suggestion was instrumental in finding the solution. Clearly, this line was throwing a NPE.
User user = queries.getUserById(ctx, id)
.fetchOne()
.into(User.class);
So, basically what I did was, before lodging the resultset in User, I checked whether the record itself existed or not in the table, like this.
UsersRecord usersRecord = queries.getUserById(ctx, id).fetchOne();
Then, did a null check on that object, and proceed to store record into pojo.
if (usersRecord == null) {
throw new NotFoundException("User with id " + id + " not found");
}
User user = usersRecord.into(User.class);
Tested the endpoint like this:
http://localhost:7000/users/2
The server is now finally returning NotFoundException
{
"statusCode": 404,
"title": "Not Found",
"errorMessage": "The resource you're looking for cannot be found.",
"apiPath": "/users/2"
}

updating JSON Object in spring restful web services

I want to pass a json object for the update function but its doesn't accept the json object and get an error. The error is:
the code is:
(value = "/UpdateUser/", method = RequestMethod.PUT , consumes=MediaType.APPLICATION_JSON_VALUE)
public void UpdateUser(JSONObject RequiredObject)throws UnknownHostException {
// RequiredObject=new HashMap<>();
System.out.println("hello into update " + RequiredObject);
// readJSON.UpdateUser(RequiredObject);
}
you have to receive the body of your request as a #RequestBody and you can receive this json object as a User object directly
#RequestMapping(value = "/UpdateUser/", method = RequestMethod.PUT ,
consumes=MediaType.APPLICATION_JSON_VALUE)
public void UpdateUser(#RequestBody User user) throws UnknownHostException {
// RequiredObject=new HashMap<>();
System.out.println("hello into update " + RequiredObject);
//readJSON.UpdateUser(RequiredObject);
}

How to run JUnit testing on Firebase Java with authentication?

I am currently using Firebase Authentication in my mobile app. The back end is a Spring boot application. The REST APIs on the back end relies on a token generated from Firebase Authentication to retrieve the Firebase UID (verifyIDToken method) of a user to perform further functions.
Currently, I notice that in Firebase Java API (server-based), there is no way of generating a token for a user, thus there is no easy way for me to do JUnit testing on the server that relies on user authentication. Anyone has clues on how to do so?
This is the sample code that does not work:
#RequestMapping(value = "/api/subscribeChannel/{channelid}", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<Object> subscribeChannel(#PathVariable Long channelid,#RequestHeader(value=FIREBASETOKEN, required = true) String idToken) {
DeferredResult<Object> result = new DeferredResult<Object>(DEFERREDTIMEOUT);
// test it out with a locally generated token
idToken = FirebaseAuth.getInstance().createCustomToken("valid Uid");
Task<FirebaseToken> task = FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
logger.info("Subscribe channel on success");
// do something
ret.setStatus("success");
ret.setMessage("channel id " + channelid + " subscribed");
result.setResult(ret);
} else {
result.setErrorResult(retStatus.getMessage());
}
}
}) .addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception arg0) {
Exception te = new TokenNotFoundException(idToken);
logger.error("Token Not Found for " + idToken);
result.setErrorResult(te);
}
});
return result;
}
The custom token you get is different from the ID token that you use to log on. To get an id token from a custom token, do this:
private static final String ID_TOOLKIT_URL =
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken";
private static final JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
private static final HttpTransport transport = Utils.getDefaultTransport();
private static final String FIREBASE_API_KEY = "<your api key here>";
private String signInWithCustomToken(String customToken) throws IOException {
GenericUrl url = new GenericUrl(ID_TOOLKIT_URL + "?key="
+ FIREBASE_API_KEY);
Map<String, Object> content = ImmutableMap.<String, Object>of(
"token", customToken, "returnSecureToken", true);
HttpRequest request = transport.createRequestFactory().buildPostRequest(url,
new JsonHttpContent(jsonFactory, content));
request.setParser(new JsonObjectParser(jsonFactory));
com.google.api.client.http.HttpResponse response = request.execute();
try {
GenericJson json = response.parseAs(GenericJson.class);
return json.get("idToken").toString();
} finally {
response.disconnect();
}
}
The Java API to generate custom tokens is documented under Create custom tokens using the Firebase SDK.
From there:
String uid = "some-uid";
String customToken = FirebaseAuth.getInstance().createCustomToken(uid);

ConfirmBehavior dosen't support Ajax rendreing

After an Ajax update of a button with a ConfirmBehavior, all Confirm dialog attributes (Header, Message, Icon) becomes Null.
Its look like thoses values are evaluated during the buildView phase only (applyMetadata function)
In the getHeader()/getMessage()/getIcon() methods of the ConfirmBehavior there is no evaluation of expression.
How to get the real expression at this point ? (to evaluate it during the render phase)
Not a perfect solution
public class ConfirmBehavior extends ClientBehaviorBase {
private String header;
private String message;
private String icon;
#Override
public String getScript(ClientBehaviorContext behaviorContext) {
FacesContext context = behaviorContext.getFacesContext();
UIComponent component = behaviorContext.getComponent();
String source = component.getClientId(context);
if(component instanceof Confirmable) {
String headerExpr = (String) component.getAttributes().get("confirm_header");
if (headerExpr!=null)
this.header = (String) ContextUtil.eval(context, headerExpr);
String messageExpr = (String) component.getAttributes().get("confirm_message");
if (messageExpr!=null)
this.message = (String) ContextUtil.eval(context, messageExpr);
String iconExpr = (String) component.getAttributes().get("confirm_icon");
if (iconExpr!=null)
this.icon = (String) ContextUtil.eval(context, iconExpr);
String script = "PrimeFaces.confirm({source:'" + source + "',header:'" + getHeader() + "',message:'" + getMessage() + "',icon:'" + getIcon() + "'});return false;";
((Confirmable) component).setConfirmationScript(script);
return null;
}
else {
throw new FacesException("Component " + source + " is not a Confirmable. ConfirmBehavior can only be attached to components that implement org.primefaces.component.api.Confirmable interface");
}
}
...
}

SmartGWT RestDataSource JSON response text does not appear to be in standard response format

I have a web-based application with GWT 2.5.1, SmartGWT 4.0, Spring 3.2.3.Release, and Hibernate 4.1. The front-end uses a SmartGWT RestDataSource that passes data to RESTful web-service, a Spring MVC Controller, that passes data to the front end with Java.
The Controller is unit tested and works great, I use a GET to pass back the data in JSON, the controller calls the back-end, gets my data and I return a UserEntity back to the RestDataSource in JSON format.
The error is:
[ERROR] [TestAdmin] - 22:01:22.432:XRP8:WARN:RestDataSource:restLoginDS:RestDataSouce transformResponse(): JSON response text does not appear to be in standard response format.
I have done a lot of Googling, and looking on this site, and I can find people with similar issues, but no good solutions.
Here is the RestDataSource:
public class LoginDataSource extends RestDataSource
{
private static LoginDataSource instance = null;
public static LoginDataSource getInstance()
{
if (instance == null)
{
instance = new LoginDataSource("restLoginDS");
}
return instance;
}
private LoginDataSource(String id)
{
setID(id);
setClientOnly(false);
// set up FETCH to use GET requests
OperationBinding fetch = new OperationBinding();
fetch.setOperationType(DSOperationType.FETCH);
fetch.setDataProtocol(DSProtocol.GETPARAMS);
DSRequest fetchProps = new DSRequest();
fetchProps.setHttpMethod("GET");
fetch.setRequestProperties(fetchProps);
// set up ADD to use POST requests
OperationBinding add = new OperationBinding();
add.setOperationType(DSOperationType.ADD);
add.setDataProtocol(DSProtocol.POSTMESSAGE);
// ===========================================
DSRequest addProps = new DSRequest();
addProps.setHttpMethod("POST");
// addProps.setContentType("application/json");
add.setRequestProperties(addProps);
// set up UPDATE to use PUT
OperationBinding update = new OperationBinding();
update.setOperationType(DSOperationType.UPDATE);
update.setDataProtocol(DSProtocol.POSTMESSAGE);
// ===========================================
DSRequest updateProps = new DSRequest();
updateProps.setHttpMethod("PUT");
// updateProps.setContentType("application/json");
update.setRequestProperties(updateProps);
// set up REMOVE to use DELETE
OperationBinding remove = new OperationBinding();
remove.setOperationType(DSOperationType.REMOVE);
DSRequest removeProps = new DSRequest();
removeProps.setHttpMethod("DELETE");
remove.setRequestProperties(removeProps);
// apply all the operational bindings
setOperationBindings(fetch, add, update, remove);
init();
}
private DataSourceIntegerField userIdField; // "userId":"1",
private DataSourceTextField usernameField; // "username":"myusername",
private DataSourceTextField passwordField; // "password":"mypassword",
private DataSourceBooleanField userActiveField; // "active":true,
private DataSourceTextField fullnameField; // "fullname":"Thomas Holmes",
private DataSourceDateField birthdateField; // "birthdate":"1960-10-30",
private DataSourceTextField emailField; // "email":"myemail#test.net",
private DataSourceTextField cellPhoneField; // "cellPhone":"111-222-1234"
private DataSourceIntegerField updatedByField; // "updatedBy":1,
private DataSourceDateField updatedDateField; // "updatedDate":"2013-01-01",
private DataSourceIntegerField createdByField; // "createdBy":1,
private DataSourceDateField createdDateField; // "createdDate":"2013-01-01",
private DataSourceTextField securityQuestion1Field; // "securityQuestion1":"peanuts",
private DataSourceTextField securityAnswer1Field; // "securityAnswer1":"linus"
protected void init()
{
System.out.println("init: START");
setDataFormat(DSDataFormat.JSON);
setJsonRecordXPath("/");
// set the values for the datasource
userIdField = new DataSourceIntegerField(Constants.USER_ID, Constants.TITLE_USER_ID);
userIdField.setPrimaryKey(true);
userIdField.setCanEdit(false);
usernameField = new DataSourceTextField(Constants.USER_USERNAME, Constants.TITLE_USER_USERNAME);
usernameField.setCanEdit(false);
passwordField = new DataSourceTextField(Constants.USER_PASSWORD, Constants.TITLE_USER_PASSWORD);
passwordField.setCanEdit(false);
userActiveField = new DataSourceBooleanField(Constants.USER_ACTIVE, Constants.TITLE_USER_ACTIVE);
fullnameField = new DataSourceTextField(Constants.USER_FULLNAME, Constants.TITLE_USER_FULLNAME);
birthdateField = new DataSourceDateField(Constants.USER_BIRTHDATE, Constants.TITLE_USER_BIRTHDATE);
emailField = new DataSourceTextField(Constants.USER_EMAIL, Constants.TITLE_USER_EMAIL);
cellPhoneField = new DataSourceTextField(Constants.USER_CELL_PHONE, Constants.TITLE_USER_CELL_PHONE);
securityQuestion1Field =
new DataSourceTextField(Constants.USER_SECURITY_QUESTION_1, Constants.TITLE_USER_SECURITY_QUESTION_1);
securityAnswer1Field =
new DataSourceTextField(Constants.USER_SECURITY_ANSWER_1, Constants.TITLE_USER_SECURITY_ANSWER_1);
updatedByField = new DataSourceIntegerField(Constants.USER_UPDATED_BY, Constants.TITLE_USER_UPDATED_BY);
updatedDateField = new DataSourceDateField(Constants.USER_UPDATED_DATE, Constants.TITLE_USER_UPDATED_DATE);
createdByField = new DataSourceIntegerField(Constants.USER_CREATED_BY, Constants.TITLE_USER_CREATED_BY);
createdDateField = new DataSourceDateField(Constants.USER_CREATED_DATE, Constants.TITLE_USER_CREATED_DATE);
System.out.println("init: FINISH");
setFields(userIdField, usernameField, passwordField, userActiveField, emailField, cellPhoneField,
fullnameField, birthdateField, securityQuestion1Field, securityAnswer1Field, updatedByField,
updatedDateField, createdByField, createdDateField);
// setFetchDataURL(getServiceRoot() + "/userId/{id}");
// setFetchDataURL(getServiceRoot() + "/contactId/{id}");
setAddDataURL(getServiceRoot() + "/create");
setUpdateDataURL(getServiceRoot() + "/update");
setRemoveDataURL(getServiceRoot() + "/remove/{id}");
}
protected String getServiceRoot()
{
return "rest/login/";
}
protected String getPrimaryKeyProperty()
{
return "userId";
}
/*
* Implementers can override this method to create a different override.
*/
#SuppressWarnings("rawtypes")
protected void postProcessTransform(DSRequest request)
{
System.out.println("LoginDataSource: postProcessTransform: START");
StringBuilder url = new StringBuilder(getServiceRoot());
System.out.println("LoginDataSource: postProcessTransform: url=" + url);
Map dataMap = request.getAttributeAsMap("data");
System.out.println("LoginDataSource: postProcessTransform: dataMap=" + dataMap.toString());
if (request.getOperationType() == DSOperationType.FETCH && dataMap.size() > 0)
{
if (dataMap.get(Constants.USER_USERNAME) != null && dataMap.get(Constants.USER_PASSWORD) != null)
{
url.append("user/" + dataMap.get(Constants.USER_USERNAME));
url.append("/pwd/" + dataMap.get(Constants.USER_PASSWORD));
}
else if (dataMap.get(Constants.USER_USERNAME) != null && dataMap.get(Constants.USER_PASSWORD) == null)
{
url.append("user/" + dataMap.get(Constants.USER_USERNAME));
url.append("/pwd/" + dataMap.get(Constants.USER_PASSWORD));
}
else if (dataMap.get(Constants.USER_EMAIL) != null)
{
url.append("email/" + dataMap.get(Constants.USER_EMAIL));
}
}
System.out.println("LoginDataSource: postProcessTransform: url=" + url.toString());
request.setActionURL(URL.encode(url.toString()));
}
#Override
protected Object transformRequest(DSRequest dsRequest)
{
// now post process the request for our own means
postProcessTransform(dsRequest);
System.out.println("LoginDataSource: transformRequest: START");
dsRequest.setContentType("application/json");
JavaScriptObject jso = dsRequest.getData();
String jsoText = JSON.encode(jso);
System.out.println("LoginDataSource: transformRequest: START: jsoText=" + jsoText);
// this code is used only when there is a password change, otherwise this will be skipped
String userPassword = JSOHelper.getAttribute(jso, Constants.USER_NEW_PASSWORD);
if (userPassword != null)
{
// This creates the new JSON attribute:
// ... , "position":{"id":x}
JSOHelper.setAttribute(jso, "password", userPassword);
// remove the JSON Attribute: ... , "userPassword":"newPassword"
JSOHelper.deleteAttribute(jso, Constants.USER_NEW_PASSWORD);
}
System.out.println("LoginDataSource: transformRequest: FINISH: url=" + dsRequest.getActionURL());
String s1 = JSON.encode(jso);
System.out.println("LoginDataSource: transformRequest: FINISH: s1=" + s1);
return s1;
}
protected void transformResponse(DSResponse response, DSRequest request, Object jsonData)
{
System.out.println("LoginDataSource: transformResponse: START");
JavaScriptObject jsObj = (JavaScriptObject) jsonData;
String jsoText1 = JSON.encode(jsObj);
System.out.println("LoginDataSource: transformResponse: jsoText=" + jsoText1);
System.out.println("LoginDataSource: transformResponse: jsonData=" + jsonData.getClass());
for (String attr : response.getAttributes())
{
System.out.println("LoginDataSource: transformResponse: attr=" + attr + " value="
+ response.getAttribute(attr));
}
super.transformResponse(response, request, jsonData);
}
}
The error comes up on the line:
super.transformResponse(response, request, jsonData);
I know the data coming back from the Controller is JSON data as follows:
{
"userId":1,
"username":"my_username",
"password":"my_password",
"active":true,
"fullname":"Thomas Holmes",
"birthdate":"1960-10-13",
"email":"test#test.net",
"cellPhone":"111-222-1234",
"updatedBy":1,
"updatedDate":"2013-01-01",
"createdBy":1,
"createdDate":"2013-01-01",
"securityQuestion1":"peanuts",
"securityAnswer1":"linus"
}
I have tested that these names match the datasource fields in the json data.
We should be able to see that by checking the datasource fields above.
I have also unit tested with JUnit and Jackson Mapper 2.0 that the JSON string data can be used to create a UserDTO object and a UserEntity object.
I am very much aware of the SmartClient documentation about the data that comes back from a controller and how it must match the required format. This is a SmartGWT RestDataSource and I looked at the response which looks ok.
In the transformResponse code:
for (String attr : response.getAttributes())
{
System.out.println("transformResponse: attr=" + attr + " value="
+ response.getAttribute(attr));
}
Which yields:
transformResponse: jsonData=class com.google.gwt.core.client.JavaScriptObject$
transformResponse: attr=data value=[object Object]
transformResponse: attr=startRow value=0
transformResponse: attr=status value=0
transformResponse: attr=endRow value=1
transformResponse: attr=totalRows value=1
transformResponse: attr=httpResponseCode value=200
transformResponse: attr=transactionNum value=0
transformResponse: attr=clientContext value=null
transformResponse: attr=httpHeaders value=[object Object]
transformResponse: attr=context value=[object Object]
It looks like the "Object jsonData" is a JavaScriptObject.
Ultimately, the JSON that comes back, in a JavascriptObject, I'd like to convert to a UserDTO object.
So, if I can remove this error and solve this objective that would be great.
Thanks!
UPATE
I've been testing this out, and I finally have a small test app which I think shows that Isomorphic broke the RestDataSource in SmartGWT. I say that because my application was working before-hand, and now it doesn't work.
I confirmed hat all this is 100% valid JSON data. Running through various tests on the Net.
test1.json: {"userId":1}
test2.json: {"userId":"1"}
test3.json: [{"userId":1}]
test4.json: [{"userId":"1"}]
Then I isolated to a very small app to test. This is something similar to what is on the SmartGWT Showcase.
public class TestApp implements EntryPoint
{
private DataSourceIntegerField userIdField;
public void onModuleLoad()
{
RestDataSource dataSource = new RestDataSource();
dataSource.setDataFormat(DSDataFormat.JSON);
dataSource.setDataURL("data/single_user.json");
// set the values for the datasource
userIdField = new DataSourceIntegerField("userId", "User Id");
userIdField.setPrimaryKey(true);
userIdField.setCanEdit(false);
dataSource.setFields(userIdField);
ListGrid grid = new ListGrid();
grid.setDataSource(dataSource);
grid.setWidth100();
grid.setHeight(150);
grid.setAutoFetchData(true);
grid.draw();
}
}
In every case, I get the same error message:
[ERROR] [SoccerAdmin] - 15:20:55.945:XRP6:WARN:RestDataSource:isc_RestDataSource_0:RestDataSouce transformResponse(): JSON response text does not appear to be in standard response format.
However, if I change from a RestDataSource to a DataSource, then I don't have any issues with TransformResponse.
I guess maybe I don't know what TransformResponse is supposed to do with RestDataSource, but I did read the SmartClient Docs for what it's worth.
If I find a great workaround, then I will post an answer.
Ultimately I changed my LoginDataSource from extending RestDataSource to extending DataSource and all my issues went away.
Per the documentation, my response data was complete and accurate.
Also, my actual data was a valid JSON object and verified that against several sites.
Not sure what he bug with SmartGWT RestDataSource is, but I feel that it is a bug ... unless they can explain to me why it isn't.
Hope this helps someone else!