2013-10-15 3 views
27

У меня возникла проблема, когда мой развертываемый банкер попадает в исключение, которое не возникает, когда я запускаю его локально в IntelliJ.Невозможно десериализовать экземпляр java.lang.String из токена START_OBJECT

Исключение:

Receiving an event {id=2, socket=0c317829-69bf-43d6-b598-7c0c550635bb, type=getDashboard, data={workstationUuid=ddec1caa-a97f-4922-833f-632da07ffc11}, reply=true} 
Firing getDashboard event to Socket#0c317829-69bf-43d6-b598-7c0c550635bb 
Failed invoking AtmosphereFramework.doCometSupport() 
java.lang.IllegalArgumentException: Can not deserialize instance of java.lang.String out of START_OBJECT token 
at [Source: N/A; line: -1, column: -1] 
     at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2502) 
     at org.codehaus.jackson.map.ObjectMapper.convertValue(ObjectMapper.java:2468) 
     at com.github.flowersinthesand.portal.support.DefaultDispatcher$DefaultHandler$DataParam.resolve(DefaultDispatcher.java:270) 
     at com.github.flowersinthesand.portal.support.DefaultDispatcher$DefaultHandler.handle(DefaultDispatcher.java:204) 
     at com.github.flowersinthesand.portal.support.DefaultDispatcher.fire(DefaultDispatcher.java:107) 
     at com.github.flowersinthesand.portal.support.AbstractSocketFactory.fire(AbstractSocketFactory.java:73) 
     at com.github.flowersinthesand.portal.atmosphere.AtmosphereSocketFactory.onRequest(AtmosphereSocketFactory.java:75) 
     at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:256) 
     at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:166) 
     at org.atmosphere.container.Grizzly2WebSocketSupport.service(Grizzly2WebSocketSupport.java:75) 
     at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:1342) 
     at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:219) 
     at org.atmosphere.websocket.DefaultWebSocketProcessor$2.run(DefaultWebSocketProcessor.java:183) 
     at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101) 
     at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:178) 
     at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:167) 
     at org.atmosphere.container.Grizzly2WebSocketSupport$Grizzly2WebSocketApplication.onMessage(Grizzly2WebSocketSupport.java:171) 
     at org.glassfish.grizzly.websockets.DefaultWebSocket.onMessage(DefaultWebSocket.java:164) 
     at org.glassfish.grizzly.websockets.frametypes.TextFrameType.respond(TextFrameType.java:70) 
     at org.glassfish.grizzly.websockets.DataFrame.respond(DataFrame.java:104) 
     at org.glassfish.grizzly.websockets.WebSocketFilter.handleRead(WebSocketFilter.java:221) 
     at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) 
     at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:265) 
     at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200) 
     at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:134) 
     at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112) 
     at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:78) 
     at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:770) 
     at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112) 
     at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) 
     at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) 
     at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) 
     at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:551) 
     at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:531) 
     at java.lang.Thread.run(Thread.java:781) 
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token 
at [Source: N/A; line: -1, column: -1] 
     at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163) 
     at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219) 
     at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:44) 
     at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:13) 
     at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704) 
     at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315) 
     at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2498) 
     ... 34 more 
java.lang.IllegalArgumentException: Can not deserialize instance of java.lang.String out of START_OBJECT token 
at [Source: N/A; line: -1, column: -1] Status 500 Message Server Error 

гнездо Обработчик

Я считаю, что исключение происходит, когда анализируется JSON в объект WorkstationRequest из-ниже пункта. Это обработчик сокета:

@On 
@Reply 
@JsonView({Views.WorkstationView.class}) 
public WorkstationDashboard getDashboard(@Data WorkstationRequest request) { 
    return new WorkstationDashboard(request.getWorkstation()); 
} 

Объект обработчик сокета сопоставляется:

public class WorkstationRequest { 

    /* Class to instantiate if this workstation does not already exist */ 
    private Class<? extends Workstation> workstationClass; 

    private WorkflowProcess workflowProcess; 

    private PhysicalWorkstation workstation; 

    WorkstationService workstationService; 

    /** 
    * @param workstationClass Required so when jackson maps the UUID we can auto fetch the class 
    */ 
    public WorkstationRequest(Class<? extends Workstation> workstationClass) { 
     this.workstationClass = workstationClass; 
     workstationService = (WorkstationService) ApplicationContextProvider.getApplicationContext().getBean("workstationService"); 
    } 

    /* Set the workstation based on UUID. Will register the workstation if it's new */ 
    @JsonProperty("workstationUuid") 
    public void setWorkstation(String workstationUUID) { 
     workstation = (PhysicalWorkstation)WorkstationService.getWorkstation(workstationUUID); 

     //setup new workstation 
     if (workstation == null) { 
      WorkstationEntity workstationEntity = workstationService.findByUUID(workstationUUID); 
      workstation = (PhysicalWorkstation)Workstation.factory(workstationEntity, workstationClass); 

      //register with queue 
      WorkflowProcessService.getWorkflowProcess(workstation).registerWorkstation(workstation); 
     } 
    } 

    public PhysicalWorkstation getWorkstation() { 
     return workstation; 
    } 
} 

JSON привязывается:

{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true} 

WorkstationDashboard.java

public class WorkstationDashboard { 
    private HashMap<String, Object> queue = new HashMap<String, Object>(); 

    private LinkedBlockingDeque<JobSetEntity> currentWork; 

    public WorkstationDashboard() { 
     queue.put("size", 0); 
    } 

    public WorkstationDashboard(Workstation workstation) { 
     fromWorkstation(workstation); 
    } 

    /* Populate dashboard data from a workstation */ 
    public void fromWorkstation(Workstation workstation) { 
     WorkflowProcess workflowProcess = WorkflowProcessService.getWorkflowProcess(workstation); 

     setCurrentWork(workstation.getCurrentWork()); 
     setQueueSize(workflowProcess.getQueue().size()); 
    } 

    public void setQueueSize(Integer queueSize) { 
     queue.put("size", queueSize); 
    } 

    public HashMap<String, Object> getQueue() { 
     return queue; 
    } 

    public LinkedBlockingDeque<JobSetEntity> getCurrentWork() { 
     return currentWork; 
    } 

    public void setCurrentWork(LinkedBlockingDeque<JobSetEntity> currentWork) { 
     this.currentWork = currentWork; 
    } 
} 

Я совсем не понимаю, как начать отлаживать это. Трассировка стека никогда не касается моего приложения. Я использую Maven -> Package развернуть мой .jar и выполнение его с java -jar /path-to-jar.jar

Update: Чтобы предотвратить этот вопрос от того, невероятно долго, я включил мой pom.xml здесь: http://pastebin.com/1ZUtKCfE. Я считаю, что это проблема с зависимостями, поскольку ошибка возникает только на моем развертываемом банке, а не на моем локальном ПК.

ответ

36

Вы отображения этого JSON

{ 
    "id": 2, 
    "socket": "0c317829-69bf-43d6-b598-7c0c550635bb", 
    "type": "getDashboard", 
    "data": { 
     "workstationUuid": "ddec1caa-a97f-4922-833f-632da07ffc11" 
    }, 
    "reply": true 
} 

, который содержит элемент с именем data, который имеет объект JSON в качестве значения. Вы пытаетесь десериализовать элемент с именем workstationUuid из этого объекта JSON в этот сеттер.

@JsonProperty("workstationUuid") 
public void setWorkstation(String workstationUUID) { 

Это не будет работать напрямую, потому что Джексон видит JSON_OBJECT, а не строку.

Попробуйте создать класс Data

public class Data { // the name doesn't matter 
    @JsonProperty("workstationUuid") 
    private String workstationUuid; 
    // getter and setter 
} 

переключатель вверх ваш метод

@JsonProperty("data") 
public void setWorkstation(Data data) { 
    // use getter to retrieve it 
+0

я не смог описать это в деталях, но библиотека Оправа Я m использует поле 'data' в этом массиве для моего объекта через' public WorkstationDashboard getDashboard (@Data WorkstationRequest запрос) {'. Он вызывает 'getDashboard()' из-за 'type' в этом JSON, а затем отображает' data'. Я мог ошибаться, так как я действительно не знаю, что происходит. Но так как это все работает локально на моем ПК и ломается, когда я развертываю свое приложение через .jar, похоже, что это какая-то проблема зависимости. Мой pom находится здесь: http://pastebin.com/1ZUtKCfE – Webnet

+1

@Webnet Является ли '@ Data' пользовательской аннотацией, которая связывает поле данных с JSON? Вам придется отступить, чтобы увидеть, как он генерирует аргумент «WorkstationRequest». –

+0

@SotiriosDelimanolis, SOLID man. Сэкономил мне много времени на устранение неполадок. – icfantv

4

Содержание данных настолько переменной, я думаю, что лучшая форма, чтобы определить его как «ObjectNode», а рядом создать его собственный класс для разбора:

И наконец:

частные данные ObjectNode;

+1

Ты сохранил мою долгую погоню за этим. Поле 'data' может содержать любой JSON, поэтому я не могу сопоставить его с POJO. Я искал какое-то решение, которое может содержать только значение JSON. Огромное спасибо. Просто, чтобы проверить, есть ли побочный эффект или недостатки его использования? – theGamblerRises

2

Если вы не хотите, чтобы определить отдельный класс для вложенного JSON, определение объекта вложенной JSon, как JsonNode должен работать, например:

{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true} 

@JsonProperty("data") 
    private JsonNode data; 
Смежные вопросы