Je rencontre un problème où mon pot déployable rencontre une exception qui ne se produit pas lorsque je l'exécute localement dans IntelliJ.
Exception:
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
Gestionnaire de sockets
Je crois que l'exception se produit lorsque le JSON est analysé dans un objet WorkstationRequest en raison de l'élément ci-dessous. Voici le gestionnaire de socket:
@On
@Reply
@JsonView({Views.WorkstationView.class})
public WorkstationDashboard getDashboard(@Data WorkstationRequest request) {
return new WorkstationDashboard(request.getWorkstation());
}
L'objet que le gestionnaire de socket met en correspondance avec:
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;
}
}
Le JSON en cours de mappage:
{"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;
}
}
Je ne sais pas trop comment commencer à déboguer cela. La trace de pile ne touche jamais mon application. J'utilise Maven -> Package
pour déployer mon fichier .jar et l'exécuter avec Java -jar /path-to-jar.jar
Mise à jour: Pour éviter que cette question ne soit incroyablement longue, j'ai inclus mon pom.xml ici: http://Pastebin.com/1ZUtKCfE . Je pense qu'il s'agit d'un problème de dépendance, car l'erreur ne se produit que sur mon fichier jar déployable et non sur mon PC local.
Vous mappez ce JSON
{
"id": 2,
"socket": "0c317829-69bf-43d6-b598-7c0c550635bb",
"type": "getDashboard",
"data": {
"workstationUuid": "ddec1caa-a97f-4922-833f-632da07ffc11"
},
"reply": true
}
qui contient un élément nommé data
dont la valeur est un objet JSON. Vous essayez de désérialiser l'élément nommé workstationUuid
de cet objet JSON dans ce programme de configuration.
@JsonProperty("workstationUuid")
public void setWorkstation(String workstationUUID) {
Cela ne fonctionnera pas directement car Jackson voit un JSON_OBJECT, pas une chaîne.
Essayez de créer une classe Data
public class Data { // the name doesn't matter
@JsonProperty("workstationUuid")
private String workstationUuid;
// getter and setter
}
l'interrupteur de votre méthode
@JsonProperty("data")
public void setWorkstation(Data data) {
// use getter to retrieve it
Le contenu des données est tellement variable, je pense que la meilleure forme est de le définir comme "ObjectNode" et ensuite de créer sa propre classe à analyser:
Finalement:
données ObjectNode privées;
Si vous ne souhaitez pas définir une classe distincte pour JSON imbriqué, la définition d'un objet JSON imbriqué en tant que JsonNode devrait fonctionner.
{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true}
@JsonProperty("data")
private JsonNode data;
Résolu le problème en utilisant la bibliothèque de Jackson. Les impressions sont appelées en dehors de la classe Main et toutes les classes POJO sont créées. Voici les extraits de code.
MainClass.Java
public class MainClass {
public static void main(String[] args) throws JsonParseException,
JsonMappingException, IOException {
String jsonStr = "{\r\n" + " \"id\": 2,\r\n" + " \"socket\": \"0c317829-69bf-
43d6-b598-7c0c550635bb\",\r\n"
+ " \"type\": \"getDashboard\",\r\n" + " \"data\": {\r\n"
+ " \"workstationUuid\": \"ddec1caa-a97f-4922-833f-
632da07ffc11\"\r\n" + " },\r\n"
+ " \"reply\": true\r\n" + "}";
ObjectMapper mapper = new ObjectMapper();
MyPojo details = mapper.readValue(jsonStr, MyPojo.class);
System.out.println("Value for getFirstName is: " + details.getId());
System.out.println("Value for getLastName is: " + details.getSocket());
System.out.println("Value for getChildren is: " +
details.getData().getWorkstationUuid());
System.out.println("Value for getChildren is: " + details.getReply());
}
MyPojo.Java
public class MyPojo {
private String id;
private Data data;
private String reply;
private String socket;
private String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public String getReply() {
return reply;
}
public void setReply(String reply) {
this.reply = reply;
}
public String getSocket() {
return socket;
}
public void setSocket(String socket) {
this.socket = socket;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Data.Java
public class Data {
private String workstationUuid;
public String getWorkstationUuid() {
return workstationUuid;
}
public void setWorkstationUuid(String workstationUuid) {
this.workstationUuid = workstationUuid;
}
}
RÉSULTATS:
La valeur de getFirstName est: 2 La valeur de getLastName est: 0c317829-69bf-43d6-b598-7c0c550635bb La valeur de getChildren est: ddec1caa-a22f-4922-833f-632d07ffc11 : vrai