2016-10-14 5 views
0

Ich fahre fort mit einem Protokollierungsverhalten mit dem WebSocketBehavior. Es protokolliert derzeit die richtigen Daten auf einer Konsole, löst aber auch einen schwerwiegenden Serialisierungsfehler aus. Dies liegt daran, dass ich die WicketApplication selbst als Konstruktorargument für das Verhalten bereitstelle. Ich habe versucht, mein Session-Objekt zu übergeben und damit die WebApplication zu erhalten, aber es gibt immer null zurück. Das Broadcaster-Objekt benötigt die Anwendung, um ordnungsgemäß zu funktionieren. Meine Frage ist, wie kann ich die WebApplication für das Verhalten bereitstellen, während die böse Serialisierungsfehler vermeiden? Hier ist mein Verhalten Klasse:Wicket-Serialisierungsproblem mit WebApplication

public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable { 

private static final long serialVersionUID = 1L; 

private Console console; 
private Handler logHandler; 
private Model<LogRecord> model = new Model<>(); 
private WebApplication application; 

public LogWebSocketBehavior(Console console, WebApplication application) { 
    super(); 
    configureLogger(); 
    this.console = console; 
    this.application = application; 


} 

private void configureLogger() { 

    Enumeration<String> list = LogManager.getLogManager().getLoggerNames(); 

    list.hasMoreElements(); 

    Logger l = Logger.getLogger(AppUtils.loggerName); 
    l.addHandler(getLoggerHandler()); 

} 

@Override 
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) { 
    LogRecord r = model.getObject(); 
    sendRecordToConsole(handler, r); 
} 

private Handler getLoggerHandler() { 
    return new LogHandler() { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public void publish(LogRecord record) { 
      model.setObject(record); 

      sendToAllConnectedClients("data"); 
     } 
    }; 
} 

private synchronized void sendToAllConnectedClients(String message) { 

     IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry(); 
     WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry); 


     b.broadcastAll(application, new Message()); 

} 

private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) { 

    Level level = r.getLevel(); 

    if (level.equals(Level.INFO)) { 
     console.info(handler, new SimpleFormatter().formatMessage(r)); 
    } else { 
     console.error(handler, new SimpleFormatter().formatMessage(r)); 
    } 
} 

class Message implements IWebSocketPushMessage { 

    public Message() { 

    } 

} 

} 

Hier ist die Platte, die verwendet wird, um die Nachrichten anzuzeigen:

public class FooterPanel extends Panel { 

private static final long serialVersionUID = 1L; 

private Form form; 
private Console console; 

public FooterPanel(String id) { 
    super(id); 
} 

@Override 
public void onInitialize() { 
    super.onInitialize(); 
    form = new Form("form"); 
    form.add(console = getConsole("feedback_console")); 
    console.setOutputMarkupId(true); 
    form.setOutputMarkupId(true); 
    add(form); 

    add(getLoggingBehavior()); 

} 

private Console getConsole(String id) { 
    return new Console(id) { 

     private static final long serialVersionUID = 1L; 

    }; 
} 

private WebSocketBehavior getLoggingBehavior() { 

    return new LogWebSocketBehavior(console, this.getWebApplication()); 

} 

} 

ich mein Verhalten wie folgt aktualisiert:

public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable { 

private static final long serialVersionUID = 1L; 

private Console console; 
private Handler logHandler; 
private Model<LogRecord> model = new Model<>(); 

public LogWebSocketBehavior(Console console) { 
    super(); 
    configureLogger(); 
    this.console = console; 

} 

private void configureLogger() { 

    Enumeration<String> list = LogManager.getLogManager().getLoggerNames(); 

    list.hasMoreElements(); 

    Logger l = Logger.getLogger(AppUtils.loggerName); 
    l.addHandler(getLoggerHandler()); 

} 

@Override 
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) { 
    LogRecord r = model.getObject(); 
    sendRecordToConsole(handler, r); 
} 

private Handler getLoggerHandler() { 
    return new LogHandler() { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public void publish(LogRecord record) { 
      model.setObject(record); 

      sendToAllConnectedClients("data"); 
     } 
    }; 
} 

private synchronized void sendToAllConnectedClients(String message) { 

    WebApplication application = WebApplication.get(); 
    IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry(); 
    WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry); 

    b.broadcastAll(application, new Message()); 

} 

private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) { 

    Level level = r.getLevel(); 
    String message = AppUtils.consoleDateTimeFormat.format(LocalDateTime.now()) + " - " + AppUtils.LogFormatter.formatMessage(r); 
    if (level.equals(Level.INFO)) { 
     console.info(handler, message); 
    } else { 
     console.error(handler, message); 
    } 
} 

class Message implements IWebSocketPushMessage { 

    public Message() { 

    } 

} 

} 

Und ich m zurück zu den ursprünglichen Problemen, mit denen ich begonnen habe, was folgender Fehler ist:

ERROR - ErrorLogger - Job (re port.DB5E002E046235586592E7E984338DEE3: 653 hat eine Ausnahme ausgelöst. org.quartz.SchedulerException:

Job warf eine unbehandelte Ausnahme. [Siehe nested Ausnahme: org.apache.wicket.WicketRuntimeException: Es gibt keine Anwendung auf aktuellen Thread angebracht DefaultQuartzScheduler_Worker-1] bei org.quartz.core.JobRunShell.run (JobRunShell.java:213)

at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) 

verursacht durch: org.apache.wicket.WicketRuntimeException: Es gibt keine Anwendung auf aktuellen Thread angebracht DefaultQuartzScheduler_Worker-1 bei org.apache.wicket.Application.get (Application.java:236)

at org.apache.wicket.protocol.http.WebApplication.get(WebApplication.java:160) 

at eb.wicket.behaviors.LogWebSocketBehavior.sendToAllConnectedClients(LogWebSocketBehavior.java:77) 

at eb.wicket.behaviors.LogWebSocketBehavior.access$100(LogWebSocketBehavior.java:29) 

at eb.wicket.behaviors.LogWebSocketBehavior$1.publish(LogWebSocketBehavior.java:70) 

Schließlich arbeitet als gewünscht .. Hier ist die Verhaltensklasse:

public class LogWebSocketBehavior extends WebSocketBehavior implements Serializable { 

private static final long serialVersionUID = 1L; 

private Console console; 
private Model<LogRecord> model = new Model<>(); 

public LogWebSocketBehavior(Console console) { 
    super(); 
    configureLogger(); 
    this.console = console; 

} 

private void configureLogger() { 

    Enumeration<String> list = LogManager.getLogManager().getLoggerNames(); 

    list.hasMoreElements(); 

    Logger l = Logger.getLogger(AppUtils.loggerName); 
    l.addHandler(getLoggerHandler()); 

} 

@Override 
protected synchronized void onPush(WebSocketRequestHandler handler, IWebSocketPushMessage message) { 
    LogRecord r = model.getObject(); 
    sendRecordToConsole(handler, r); 
} 

private Handler getLoggerHandler() { 
    return new LogHandler() { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public void publish(LogRecord record) { 
      model.setObject(record); 

      sendToAllConnectedClients("data"); 
     } 
    }; 
} 

private synchronized void sendToAllConnectedClients(String message) { 

    IWebSocketConnectionRegistry registry = new SimpleWebSocketConnectionRegistry(); 
    WebSocketPushBroadcaster b = new WebSocketPushBroadcaster(registry); 
    b.broadcastAll(Application.get("eb.wicket.MyWicketFilter"), new Message()); 

} 

private void sendRecordToConsole(WebSocketRequestHandler handler, LogRecord r) { 

    Level level = r.getLevel(); 
    String message = AppUtils.consoleDateTimeFormat.format(LocalDateTime.now()) + " - " + AppUtils.LogFormatter.formatMessage(r); 
    if (level.equals(Level.INFO)) { 
     console.info(handler, message); 
    } else { 
     console.error(handler, message); 
    } 
} 

class Message implements IWebSocketPushMessage { 

    public Message() { 

    } 

} 

} 

Antwort

2

Anstatt einen Verweis auf die Anwendung zu halten, suchen Sie einfach nach Bedarf: Application.get().

Nach Ihrer Frage aktualisieren wir sehen können:

Caused by: org.apache.wicket.WicketRuntimeException: 
There is no application attached to current thread DefaultQuartzScheduler_Worker-1 

Dies erklärt es - dies ist ein Faden durch Quartz gestartet, ist es nicht ein http-Thread.

Der einzige Weg, dies zu überwinden, ist Application.get(String) zu verwenden. Der Wert sollte der Anwendungsname (Anwendungsnummer getName()) sein, der in Ihrer web.xml als Wert für <filter-name> angegeben ist.

Auf diese Weise können Sie die Anwendungsinstanz abrufen, aber es gibt keine Möglichkeit, dasselbe für Session und/oder RequestCycle zu tun, falls Sie sie ebenfalls benötigen.

+0

Ich habe das versucht und ich bekomme weiterhin eine Null. Ich habe diese Antwort auf eine andere Frage gefunden und verstehe, wie sie funktionieren soll. Ich würde denken, dass es die Anwendung zurückgeben würde, aber liefert immer eine Null zurück. –

+0

So aktualisierte ich mein Code-Verhalten wie folgt: –

+0

Bitte siehe oben. –

Verwandte Themen