javascript
tomee_使用Vysper,TomEE和PrimeFaces将XMPP服务器嵌入JSF Web应用程序内部
tomee
我有一個需要在完成某些工作時通知用戶的應用程序。 它使用JSF和Primefaces,因此可以使用大氣 (也稱為Push)來實現這種通知。
但是另一個有趣的方法是使用嵌入在Java Web應用程序中的XMPP服務器。 好的,好的,您不必嵌入它,您只需運行一個工業級XMPP服務器的實例,例如Openfire和Tigase即可 。 但是,嘿,我們只是玩了一點,所以我將向您展示如何使用Vysper進行操作, Vysper是使用Apache Mina開發的概念證明,只需幾分鐘即可輕松完成。
在展示如何做之前,很高興記住線程和JEE應用程序通常不會混合使用 ,因此我們可以玩,但是我們必須知道我們在做什么。
首先,您將需要這些JAR,其中大多數來自Vysper。 只是幾個?
- aopalliance-1.0.jar
- commons-codec-1.4.jar
- commons-collections-3.1.jar
- commons-io-1.4.jar
- commons-lang-2.5.jar
- commons-logging-1.1.jar
- 并發1.3.4.jar
- derby-10.2.1.6.jar
- dnsjava-2.0.8.jar
- ehcache-core-2.2.0.jar
- fontbox-0.1.0.jar
- jackrabbit-api-1.5.0.jar
- jackrabbit-core-1.5.3.jar
- jackrabbit-jcr-commons-1.5.3.jar
- jackrabbit-spi-1.5.0.jar
- jackrabbit-spi-commons-1.5.0.jar
- jackrabbit-text-extractors-1.5.0.jar
- jcl-over-slf4j-1.5.3.jar
- jcr-1.0.jar
- jempbox-0.2.0.jar
- jetty-continuation-7.2.1.v20101111.jar
- jetty-http-7.2.1.v20101111.jar
- jetty-io-7.2.1.v20101111.jar
- jetty-security-7.2.1.v20101111.jar
- jetty-server-7.2.1.v20101111.jar
- jetty-servlet-7.2.1.v20101111.jar
- jetty-util-7.2.1.v20101111.jar
- jetty-websocket-7.2.1.v20101111.jar
- log4j-1.2.14.jar
- lucene-core-2.3.2.jar
- mina-core-2.0.2.jar
- nbxml-0.7.jar
- nekohtml-1.9.7.jar
- pdfbox-0.7.3.jar
- poi-3.0.2-FINAL.jar
- poi-scratchpad-3.0.2-FINAL.jar
- primefaces-4.0.jar
- servlet-api-2.5.jar
- slf4j-api-1.5.3.jar
- slf4j-log4j12-1.5.3.jar
- smack-3.1.0.jar
- smackx-3.1.0.jar
- spec-compliance-0.7.jar
- 彈簧-aop-3.0.5.RELEASE.jar
- 彈簧-asm-3.0.5.RELEASE.jar
- Spring Bean3.0.5.RELEASE.jar
- 彈簧上下文-3.0.5.RELEASE.jar
- 彈簧核心-3.0.5.RELEASE.jar
- spring-expression-3.0.5.RELEASE.jar
- vysper-core-0.7.jar
- vysper-websockets-0.7.jar
- xep0045-muc-0.7.jar
- xep0060-pubsub-0.7.jar
- xep0124-xep0206-bosh-0.7.jar
- xercesImpl-2.8.1.jar
- xml-apis-1.3.03.jar
現在,從Vysper復制虛假證書,以便您的XMPP服務器可以在“安全”通道下“工作”。 它稱為bogus_mina_tls.cert。
我的xhtml看起來像這樣:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"xmlns:f="http://java.sun.com/jsf/core"xmlns:h="http://java.sun.com/jsf/html"xmlns:ui="http://java.sun.com/jsf/facelets"xmlns:p="http://primefaces.org/ui"> <h:head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Messaging Prototype</title><link rel="icon" type="image/png" href="favicon.ico"></link> </h:head> <h:body> <h:outputStylesheet library="css" name="style.css" /><p:ajaxStatus style="width:16px;height:16px;" id="ajaxStatusPanel"> <f:facet name="start"> <h:graphicImage value="./ajaxloading.gif" /> </f:facet> <f:facet name="complete"> <h:outputText value="" /> </f:facet> </p:ajaxStatus> <h:form> <p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" /><p:spacer height="10" /><p:panel><h:panelGrid columns="2"><p:commandButton value="Enter" action="#{messagingMB.sendMessage}" /></h:panelGrid></p:panel><p:spacer height="10" /></h:form> </h:body> </html>很簡單吧? 托管Bean也很容易。
import java.io.Serializable;import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped;import org.jivesoftware.smack.XMPPException;@ManagedBean @ViewScoped public class MessagingMB implements Serializable {private static final long serialVersionUID = -9092497421080796430L;@EJBprivate JSFUtilEJB jsfUtilEJB;@PostConstructpublic void init() {}public void sendMessage() {try {new BasicClient().test();} catch (XMPPException e) {jsfUtilEJB.addErrorMessage(e,"Could not send");}} }當然,EJB:
import javax.ejb.Stateless; import javax.faces.application.FacesMessage; import javax.faces.application.FacesMessage.Severity; import javax.faces.context.FacesContext;@Stateless public class JSFUtilEJB {@SuppressWarnings("unchecked")public <T> T findBean(String beanName) {FacesContext context = FacesContext.getCurrentInstance();return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);}public long addErrorMessage(String msg) {return addMessage(null,FacesMessage.SEVERITY_ERROR,msg);}public long addErrorMessage(Exception e,String summary){return addMessage(e,FacesMessage.SEVERITY_ERROR,summary);}public long addFatalErrorMessage(Exception e,String summary){return addMessage(e,FacesMessage.SEVERITY_FATAL,summary);}public long addInfoMessage(String summary){return addMessage(null,FacesMessage.SEVERITY_INFO,summary);}public long addWarnMessage(Exception e,String summary){return addMessage(e,FacesMessage.SEVERITY_WARN,summary);}public long addErrorMessage(Exception e) {return addMessage(e,FacesMessage.SEVERITY_ERROR,e.getMessage(),e.getClass().getSimpleName());}private long addMessage(Exception e,Severity severity, String summary) {FacesContext context = FacesContext.getCurrentInstance();String clientId = null;long id = -1;if (e != null){id = printStackTrace(e);FacesMessage facesMessage = null;if (e.getCause() instanceof org.apache.openjpa.persistence.EntityExistsException){facesMessage = new FacesMessage(severity,"[Error: #"+id+"] "+summary,"You are trying are to add a new object that already exists or your're trying to violate a unique constraint)" ); }else{facesMessage = new FacesMessage(severity,"[Error: #"+id+"] "+summary,e.getMessage() );}context.addMessage(clientId , facesMessage );}else{FacesMessage facesMessage = new FacesMessage(severity,summary," ");context.addMessage(clientId , facesMessage );}return id;}private long addMessage(Exception e,Severity severity, String summary, String detail) {FacesContext context = FacesContext.getCurrentInstance();String clientId = null;long id = -1;if (e != null){id = printStackTrace(e); FacesMessage facesMessage = new FacesMessage(severity,"["+id+"] "+summary,detail );context.addMessage(clientId , facesMessage );}else{FacesMessage facesMessage = new FacesMessage(severity,summary,detail );context.addMessage(clientId , facesMessage );}return id;}public long printStackTrace(Exception e){long uniqueId = System.currentTimeMillis();return uniqueId;}}和
import java.io.File; import java.io.Serializable;import javax.annotation.PostConstruct; import javax.ejb.Singleton; import javax.ejb.Startup;import org.apache.vysper.mina.TCPEndpoint; import org.apache.vysper.storage.StorageProviderRegistry; import org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry; import org.apache.vysper.xmpp.addressing.EntityImpl; import org.apache.vysper.xmpp.authorization.AccountManagement; import org.apache.vysper.xmpp.server.XMPPServer;@Startup @Singleton public class XmppEJB implements Serializable {/*** <br>06/09/2014*/private static final long serialVersionUID = 1L;private boolean started;@PostConstructpublic void init() {try {// choose the storage you want to use// StorageProviderRegistry providerRegistry = new JcrStorageProviderRegistry();StorageProviderRegistry providerRegistry = new MemoryStorageProviderRegistry();final AccountManagement accountManagement = (AccountManagement) providerRegistry.retrieve(AccountManagement.class);if(!accountManagement.verifyAccountExists(EntityImpl.parse("user1@vysper.org"))) {accountManagement.addUser(EntityImpl.parse("user1@vysper.org"), "password");}if(!accountManagement.verifyAccountExists(EntityImpl.parse("user2@vysper.org"))) {accountManagement.addUser(EntityImpl.parse("user2@vysper.org"), "password");}XMPPServer server = new XMPPServer("vysper.org");server.addEndpoint(new TCPEndpoint());server.setStorageProviderRegistry(providerRegistry);server.setTLSCertificateInfo(new File("/path/to/bogus_mina_tls.cert"), "boguspw");server.start();System.out.println("server is running...");} catch (Exception e) {e.printStackTrace();}started = true;}public boolean isStarted() {return this.started;}}還有來自Vysper的基本客戶端。
import java.util.Date;import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.SASLAuthentication; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smackx.packet.Time; import org.jivesoftware.smackx.packet.Version;public class BasicClient {static class IQListener implements PacketListener {public void processPacket(Packet packet) {IQ iq = (IQ) packet;String iqString = iq.toString();System.out.println("T" + System.currentTimeMillis() + " IQ: "+ iqString + ": " + iq.toXML());}}static class PresenceListener implements PacketListener {public void processPacket(Packet packet) {Presence presence = (Presence) packet;String iqString = presence.toString();final PacketExtension extension = presence.getExtension("http://jabber.org/protocol/caps");if (extension != null)System.out.println("T" + System.currentTimeMillis() + " Pres: "+ iqString + ": " + presence.toXML());}}public void test() throws XMPPException {String me = "user2@vysper.org";String to = "user1@vysper.org";try {ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration("localhost");connectionConfiguration.setCompressionEnabled(false);connectionConfiguration.setSelfSignedCertificateEnabled(true);connectionConfiguration.setExpiredCertificatesCheckEnabled(false); // connectionConfiguration.setDebuggerEnabled(true);connectionConfiguration.setSecurityMode(ConnectionConfiguration.SecurityMode.required); // XMPPConnection.DEBUG_ENABLED = true;XMPPConnection connection = new XMPPConnection(connectionConfiguration);connection.connect();SASLAuthentication saslAuthentication = connection.getSASLAuthentication();saslAuthentication.authenticate(me, "password", "test");connection.login(me, "pqssword");connection.getRoster().setSubscriptionMode(Roster.SubscriptionMode.accept_all);connection.addPacketListener(new IQListener(), new PacketFilter() {public boolean accept(Packet packet) {return packet instanceof IQ;}});connection.addPacketListener(new PresenceListener(),new PacketFilter() {public boolean accept(Packet packet) {return packet instanceof Presence;}});Chat chat = null;if (to != null) {Presence presence = new Presence(Presence.Type.subscribe);presence.setFrom(connection.getUser());String toEntity = to;presence.setTo(toEntity);connection.sendPacket(presence);chat = connection.getChatManager().createChat(toEntity,new MessageListener() {public void processMessage(Chat inchat,Message message) {System.out.println("log received message: "+ message.getBody());}});}connection.sendPacket(new Presence(Presence.Type.available,"pommes", 1, Presence.Mode.available));Thread.sleep(1000);// query server versionsendIQGetWithTimestamp(connection, new Version());// query server timesendIQGetWithTimestamp(connection, new Time());chat.sendMessage("Hello " + to + " at " + new Date());connection.disconnect();} catch (Throwable e) {e.printStackTrace(); // To change body of catch statement use File |// Settings | File Templates.}System.out.println("bye");}private static void sendIQGetWithTimestamp(XMPPConnection connection, IQ iq) {iq.setType(IQ.Type.GET);connection.sendPacket(iq);System.out.println("T" + System.currentTimeMillis()+ " IQ request sent");} }我們快要準備好了。 當然,現在我們需要一個XMPP客戶端,例如Pidgin 。
首先,我只想對本博客表示感謝 ,因為我不知道為什么,Vysper站點幾乎沒有關于如何配置Pidgin的信息,因此該博客文章非常有用。
讓我向您展示我的pidgin用戶的樣子:
我知道,是葡萄牙語。
就是這樣。 我們都準備好了。 啟動您的JSF Web應用程序并播放。
注意,通信是雙向的,因此您可以僅使用XMPP客戶端將命令發送到服務器。 為此,您只需要更改此偵聽器即可:
chat = connection.getChatManager().createChat(toEntity,new MessageListener() {public void processMessage(Chat inchat,Message message) {System.out.println("log received message: "+ message.getBody());}});我想知道是否可以創建一個DSL來處理一些命令,是否可以找到一些自動完成的pidgin插件來使用此DSL編寫命令。 歡迎提出建議!
ps。 EJB不能正常關閉服務器。 但是我敢打賭,如果服務器關閉,有一些EJB注釋可以做到這一點。
翻譯自: https://www.javacodegeeks.com/2014/09/embedding-a-xmpp-server-inside-your-jsf-web-application-using-vysper-tomee-and-primefaces.html
tomee
總結
以上是生活随笔為你收集整理的tomee_使用Vysper,TomEE和PrimeFaces将XMPP服务器嵌入JSF Web应用程序内部的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大学生和高三毕业生暑假赚钱避坑指南?
- 下一篇: 在Spring中使用@ResponseS