Skip to content

Issue deserializing JSON object when using SpringFox with Jackson #829

@logicsec-zz

Description

@logicsec-zz
  • I have checked that the [SDK documentation][sdk-docs] doesn't solve my issue.
  • I have checked that the [API documentation][api-docs] doesn't solve my issue.
  • I have searched the [Box Developer Forums][dev-forums] and my issue isn't already reported (or if it has been reported, I have attached a link to it, for reference).
  • I have searched [Issues in this repo][github-repo] and my issue isn't already reported.

Description of the Issue

I am currently working on building a middleware application between our ERP and Box. We wanted to use the SDK but are running into an issue. The current setup is using Swagger and SpringFox. When we attempt to return a JSON object, it appears Jackson is having an issue deserializing the object and giving us the following error:

{
  "timestamp": "2020-07-21T18:53:48.574+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Could not write JSON: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d] (through reference chain: com.box.sdk.BoxCollaboration$Info[\"createdBy\"]->com.box.sdk.BoxUser$Info[\"resource\"]->com.box.sdk.BoxUser[\"avatar\"])",
  "trace": "org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d] (through reference chain: com.box.sdk.BoxCollaboration$Info[\"createdBy\"]->com.box.sdk.BoxUser$Info[\"resource\"]->com.box.sdk.BoxUser[\"avatar\"])\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:326)\r\n\tat org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:287)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:181)\r\n\tat org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:123)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)\r\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:660)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:741)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:109)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:832)\r\nCaused by: com.fasterxml.jackson.databind.JsonMappingException: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d] (through reference chain: com.box.sdk.BoxCollaboration$Info[\"createdBy\"]->com.box.sdk.BoxUser$Info[\"resource\"]->com.box.sdk.BoxUser[\"avatar\"])\r\n\tat com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397)\r\n\tat com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:356)\r\n\tat com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316)\r\n\tat com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:730)\r\n\tat com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)\r\n\tat com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)\r\n\tat com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)\r\n\tat com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)\r\n\tat com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)\r\n\tat com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)\r\n\tat com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166)\r\n\tat com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)\r\n\tat com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)\r\n\tat com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1433)\r\n\tat com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:921)\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:317)\r\n\t... 52 more\r\nCaused by: com.box.sdk.BoxAPIResponseException: The API returned an error code [404 | .038da827f44a95db6b57892565ac89f9d]\r\n\tat com.box.sdk.BoxAPIResponse.<init>(BoxAPIResponse.java:92)\r\n\tat com.box.sdk.BoxAPIRequest.trySend(BoxAPIRequest.java:581)\r\n\tat com.box.sdk.BoxAPIRequest.send(BoxAPIRequest.java:354)\r\n\tat com.box.sdk.BoxAPIRequest.send(BoxAPIRequest.java:329)\r\n\tat com.box.sdk.BoxUser.getAvatar(BoxUser.java:511)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\r\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\r\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\r\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:564)\r\n\tat com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688)\r\n\tat com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:722)\r\n\t... 64 more\r\n",
  "path": "/api/collaborations/116952186700/new"
}

Classes

Controller

package com.amteck.coinsbox.folder.rest;

import com.amteck.coinsbox.folder.models.Folder;
import com.amteck.coinsbox.folder.models.ItemsInFolder;
import com.amteck.coinsbox.folder.models.Parent;
import com.amteck.coinsbox.folder.service.FolderService;
import com.google.common.base.Strings;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;

@Api(value = "FolderController")
@RestController
@RequestMapping(value = "/api")
public class FolderController {

    @Autowired
    private FolderService folderService;

    @ApiOperation(value = "Get List of Items in Folder")
    @GetMapping(value = "/folders/{id}/items")
    public ItemsInFolder getItemsInFolder(@PathVariable(value = "id") String id) throws IOException {
        if (Strings.isNullOrEmpty(id)) {
            id = "0";
        }
        return this.folderService.getItemsInFolder(id);
    }

    @ApiOperation(value = "Get Folder Information")
    @GetMapping(value = "/folders/{id}")
    public Folder getFolderInfo(@PathVariable(value = "id") String id) throws IOException {
        if (Strings.isNullOrEmpty(id)) {
            id = "0";
        }

        return this.folderService.getFolderInfo(id);
    }

    @ApiOperation(value = "Create Folder")
    @PostMapping(value = "/folders")
    @Transactional
    public Folder createFolder(@RequestBody Parent parent,
                               @RequestParam(value = "name") String newFolderName) throws IOException {

        return this.folderService.createFolder(newFolderName, parent);
    }

    @ApiOperation(value = "Copy Folder")
    @PostMapping(value = "/folders/{folder_id}/copy")
    @Transactional
    public Folder copyFolder(@PathVariable(value = "folder_id") String folderId,
                             @RequestBody String newFolderName,
                             @RequestParam(value = "parentId", required = false) String parentId) throws IOException {

        return this.folderService.copyFolder(folderId, newFolderName, parentId);
    }

    @ApiOperation(value = "update or move Folder")
    @PutMapping(value = "/folders/{folder_id}")
    @Transactional
    public Folder updateFolder(@PathVariable(value = "folder_id") String folderId,
                               @RequestParam(required = false) String newFolderName,
                               @RequestParam(required = false) String parentDestinationId) throws IOException {

        if (Strings.isNullOrEmpty(parentDestinationId)) {
            return this.folderService.updateFolder(folderId, newFolderName);
        } else {
            return this.folderService.moveFolder(folderId, newFolderName, parentDestinationId);
        }
    }
}

Service

package com.amteck.coinsbox.folder.service;

import com.amteck.coinsbox.authorization.service.AuthService;
import com.amteck.coinsbox.folder.business.EntryConverter;
import com.amteck.coinsbox.folder.business.FolderConverter;
import com.amteck.coinsbox.folder.models.*;
import com.box.sdk.*;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@ComponentScan("com/box/sdk/")
public class FolderService extends BoxJSONObject {
    private static final Logger LOG = LoggerFactory.getLogger(FolderService.class);

    @Inject private AuthService authService;
    @Inject private FolderConverter folderConverter;
    @Inject private EntryConverter entryConverter;

    public ItemsInFolder getItemsInFolder(String folderId) throws IOException {

        BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();
        BoxFolder folder = new BoxFolder(api, folderId);
        Integer totalCount = 0;

        ItemsInFolder itemsInFolderList = new ItemsInFolder();
        List<Entry> entries = new ArrayList<>();

        for (BoxItem.Info itemInfo : folder) {
            if (itemInfo instanceof BoxFolder.Info) {
                BoxFolder.Info folderInfo = (BoxFolder.Info) itemInfo;
                entries.add(entryConverter.convert(folderInfo));
                totalCount += 1;
            }
        }

        itemsInFolderList.setEntries(entries);
        itemsInFolderList.setTotalCount(totalCount);

        return itemsInFolderList;
    }

    public Folder getFolderInfo(String folderId) throws IOException {
        BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();

        BoxFolder folder = new BoxFolder(api, folderId);
        BoxFolder.Info info = folder.getInfo("id", "type", "created_by", "name", "owned_by", "parent");

        return folderConverter.convert(info);
    }

    public Folder createFolder(String newFolderName, Parent parent) throws IOException {
        BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();
        BoxFolder parentFolder = new BoxFolder(api, parent.getId());
        BoxFolder.Info childFolderInfo = parentFolder.createFolder(newFolderName);

        return folderConverter.convert(childFolderInfo);
    }

    public Folder copyFolder(String folderId, String newFolderName, String parentId) throws IOException {
        if (folderId == null) {
            throw new IllegalArgumentException("Parameter 'folderId' can not be null");
        }

        BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();
        BoxFolder folder = new BoxFolder(api, folderId);

        String parent = "";

        System.out.println(parentId);

        if (Strings.isNullOrEmpty(parentId)) {
            BoxFolder.Info parentFolderInfo = folder.getInfo().getParent();
            BoxFolder parentFolder = parentFolderInfo.getResource();
            parent = parentFolder.getID();
        } else {
            parent = parentId;
        }

        System.out.println(parent);

        BoxFolder destination = new BoxFolder(api, parent);

        if (!Strings.isNullOrEmpty(newFolderName)) {
            folder.copy(destination, newFolderName);
        } else {
            folder.copy(destination);
        }

        return folderConverter.convert(folder.getInfo("id", "type", "created_by", "name", "owned_by", "parent"));

    }

    public Folder updateFolder(String folderId, String newFolderName) throws IOException {
        if (Strings.isNullOrEmpty(folderId)) {
            throw new IllegalArgumentException("Parameter 'folderId' can not be null");
        }
        BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();

        BoxFolder folder = new BoxFolder(api, folderId);

        BoxFolder.Info info = folder.new Info();
        info.setName(newFolderName);
        folder.updateInfo(info);
        return folderConverter.convert(folder.getInfo("id", "type", "created_by", "name", "owned_by", "parent"));

    }

    public Folder moveFolder(String folderId,
                             String newFolderName,
                             String destinationFolderId) throws IOException {
        try {
            BoxDeveloperEditionAPIConnection api = authService.requestAccessToken();
            LOG.debug("Moving folder(id=" + folderId + ") to destination_folder(id=" + destinationFolderId + ")"
                    + (newFolderName == null ? "" : " with new name '" + newFolderName + "'"));
            if (folderId == null) {
                throw new IllegalArgumentException("Parameter 'folderId' can not be null");
            }
            if (destinationFolderId == null) {
                throw new IllegalArgumentException("Parameter 'destinationFolderId' can not be null");
            }
            BoxFolder folderToMove = new BoxFolder(api, folderId);
            BoxFolder destinationFolder = new BoxFolder(api, destinationFolderId);
            BoxFolder folder;

            if (newFolderName == null) {
                folder = (BoxFolder) folderToMove.move(destinationFolder).getResource();
            } else {
                folder = (BoxFolder) folderToMove.move(destinationFolder, newFolderName).getResource();
            }
            return folderConverter.convert(folder.getInfo());
        } catch (BoxAPIException e) {
            throw new RuntimeException(
                    String.format("Box API returned the error code %d\n\n%s", e.getResponseCode(), e.getResponse()), e);
        }
    }
}

Any help is greatly appreciated. We have been needing to build the JSON which is taking a lot of time and I think if we can get this issue fixed we can speed things up a bit.

Metadata

Metadata

Labels

bugAdded to issues that describes SDK bug

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions