Ich stoße auf ein Problem, bei dem mein bereitstellbares JAR auf eine Ausnahme stößt, die nicht auftritt, wenn ich dies lokal in IntelliJ ausführe.
Ausnahme:
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
Socket Handler
Ich glaube, die Ausnahme tritt auf, wenn der JSON aufgrund des folgenden Elements in ein WorkstationRequest-Objekt analysiert wird. Dies ist der Socket-Handler:
@On
@Reply
@JsonView({Views.WorkstationView.class})
public WorkstationDashboard getDashboard(@Data WorkstationRequest request) {
return new WorkstationDashboard(request.getWorkstation());
}
Das Objekt, dem der Socket-Handler zugeordnet ist:
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;
}
}
Der zugeordnete 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;
}
}
Ich bin ziemlich ratlos, wie ich mit dem Debuggen beginnen soll. Die Stapelverfolgung berührt meine Anwendung nie. Ich verwende Maven -> Package
meine .jar-Datei und führe sie mit ausjava -jar /path-to-jar.jar
Update: Um zu verhindern, dass diese Frage unglaublich lang wird, habe ich meine pom.xml hier eingefügt: http://pastebin.com/1ZUtKCfE . Ich glaube, dies ist ein Abhängigkeitsproblem, da der Fehler nur auf meinem bereitstellbaren JAR und nicht auf meinem lokalen PC auftritt.
quelle
data
Feld in diesem Array über meinem Objekt zupublic WorkstationDashboard getDashboard(@Data WorkstationRequest request) {
. Es ruftgetDashboard()
wegen destype
in diesem JSON auf und ordnet dann zudata
. Ich könnte mich irren, da ich nicht wirklich weiß, was los ist. Da dies alles lokal auf meinem PC funktioniert und beim Bereitstellen meiner Anwendung über eine .jar-Datei unterbrochen wird, scheint es sich um ein Abhängigkeitsproblem zu handeln. Mein Pom ist hier: pastebin.com/1ZUtKCfE@Data
eine benutzerdefinierte Anmerkung, die dasdata
Feld vom JSON bindet ? Sie müssen zurückverfolgen, um zu sehen, wie dasWorkstationRequest
Argument generiert wird .data
Feld enthalten wird. Gibt es irgendwelche Probleme? stackoverflow.com/questions/39053106/…JsonNode
. Dies koppelt Ihren Code jedoch mit Jackson und macht es nicht einfach, diesen Wert dann zu verwenden.Wenn Sie keine separate Klasse für verschachtelten JSON definieren möchten, sollte das Definieren eines verschachtelten JSON-Objekts als JsonNode beispielsweise funktionieren:
{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true} @JsonProperty("data") private JsonNode data;
quelle
Der Dateninhalt ist so variabel, dass ich denke, die beste Form ist, ihn als "ObjectNode" zu definieren und als nächstes seine eigene Klasse zum Parsen zu erstellen:
Schließlich:
private ObjectNode-Daten;
quelle
data
Feld kann sich ein beliebiger JSON befinden, daher kann ich ihn keinem POJO zuordnen. Ich habe nach einer Lösung gesucht, die nur JSON-Werte enthalten kann. Ich danke dir sehr. Gibt es irgendwelche Nebeneffekte oder Nachteile bei der Verwendung?Das Problem mit der Jackson-Bibliothek wurde behoben. Drucke werden aus der Hauptklasse aufgerufen und alle POJO-Klassen werden erstellt. Hier sind die Codefragmente.
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; } }
ERGEBNISSE:
quelle
Auf diese Weise habe ich mein Problem gelöst. Hoffe es hilft anderen. In meinem Fall habe ich eine Klasse, ein Feld, ihren Getter & Setter erstellt und dann das Objekt anstelle einer Zeichenfolge bereitgestellt.
Benutze das
public static class EncryptedData { private String encryptedData; public String getEncryptedData() { return encryptedData; } public void setEncryptedData(String encryptedData) { this.encryptedData = encryptedData; } } @PutMapping(value = MY_IP_ADDRESS) public ResponseEntity<RestResponse> updateMyIpAddress(@RequestBody final EncryptedData encryptedData) { try { Path path = Paths.get(PUBLIC_KEY); byte[] bytes = Files.readAllBytes(path); PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(base64.decode(bytes)); PrivateKey privateKey = KeyFactory.getInstance(CRYPTO_ALGO_RSA).generatePrivate(ks); Cipher cipher = Cipher.getInstance(CRYPTO_ALGO_RSA); cipher.init(Cipher.PRIVATE_KEY, privateKey); String decryptedData = new String(cipher.doFinal(encryptedData.getEncryptedData().getBytes())); String[] dataArray = decryptedData.split("|"); Method updateIp = Class.forName("com.cuanet.client.helper").getMethod("methodName", String.class,String.class); updateIp.invoke(null, dataArray[0], dataArray[1]); } catch (Exception e) { LOG.error("Unable to update ip address for encrypted data: "+encryptedData, e); } return null;
An Stelle von
@PutMapping(value = MY_IP_ADDRESS) public ResponseEntity<RestResponse> updateMyIpAddress(@RequestBody final EncryptedData encryptedData) { try { Path path = Paths.get(PUBLIC_KEY); byte[] bytes = Files.readAllBytes(path); PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(base64.decode(bytes)); PrivateKey privateKey = KeyFactory.getInstance(CRYPTO_ALGO_RSA).generatePrivate(ks); Cipher cipher = Cipher.getInstance(CRYPTO_ALGO_RSA); cipher.init(Cipher.PRIVATE_KEY, privateKey); String decryptedData = new String(cipher.doFinal(encryptedData.getBytes())); String[] dataArray = decryptedData.split("|"); Method updateIp = Class.forName("com.cuanet.client.helper").getMethod("methodName", String.class,String.class); updateIp.invoke(null, dataArray[0], dataArray[1]); } catch (Exception e) { LOG.error("Unable to update ip address for encrypted data: "+encryptedData, e); } return null; }
quelle