2016-10-14 34 views
0

我繼續使用WebSocketBehavior進行日誌記錄。它當前將正確的數據記錄到控制檯,但也會引發可怕的序列化錯誤。這是因爲我正在提供WicketApplication本身作爲行爲的構造器參數。我試過將它傳遞給會話對象,並使用它來獲取WebApplication,但它始終返回null。廣播者對象需要應用程序才能正常工作。我的問題是如何提供WebApplication的行爲,同時避免討厭的序列化錯誤?這裏是我的行爲類:WebApplication的Wicket序列化問題

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() { 

    } 

} 

} 

這裏是用來顯示消息的面板:

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()); 

} 

} 

我更新了我的行爲如下:

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() { 

    } 

} 

} 

而且我回到原來的問題,我開始,這是以下錯誤:

錯誤 - ErrorLogger - 作業(重新port.DB5E002E046235586592E7E984338DEE3:653拋出異常。 org.quartz.SchedulerException:

作業拋出未處理的異常。 [見嵌套異常:org.apache.wicket.WicketRuntimeException:沒有附着到當前線程DefaultQuartzScheduler_Worker-1應用]在 org.quartz.core.JobRunShell.run(JobRunShell.java:213)

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

org.apache.wicket.WicketRuntimeException:通過引起沒有DefaultQuartzScheduler_Worker-1 在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) 

最後工作作爲期望..這是行爲類:

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() { 

    } 

} 

} 

回答

2

代替保留對應用程序的引用,只需在需要時查找它即可:Application.get()

更新您的問題後,我們可以看到:

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

這解釋了它 - 這是由石英啓動一個線程,它不是一個HTTP線程。

解決此問題的唯一方法是使用Application.get(String)。值應該是應用程序名稱(Application#getName()),它在web.xml中被指定爲<filter-name>的值。

這樣你就可以得到應用程序實例,但是如果你需要的話,也無法爲Session和/或RequestCycle做同樣的事情。

+0

我試過了,我繼續得到一個null。我在另一個問題上找到了答案,並理解它應該如何工作。我會認爲它會返回應用程序,但始終返回一個空值。 –

+0

因此,我更新了我的代碼行爲,如下所示: –

+0

請參閱上文。 –