使用Vysper,TomEE和PrimeFaces将XMPP服务器嵌入JSF Web应用程序内部

我有一个需要在完成某些工作时通知用户的应用程序。 它使用JSF和Primefaces,因此可以使用大气(也称为Push)实现这种通知。

但是另一个有趣的方法是使用嵌入在Java Web应用程序中的XMPP服务器。 好的,好的,您不必嵌入它,您只需运行具有工业实力的XMPP服务器的实例,例如OpenfireTigase即可。 但是,嘿,我们只是玩了一点,所以我将向您展示如何使用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
  • spring-aop-3.0.5.RELEASE.jar
  • 弹簧-asm-3.0.5.RELEASE.jar
  • Spring Bean3.0.5.RELEASE.jar
  • spring-context-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;
    
    @EJB
    private JSFUtilEJB jsfUtilEJB;
    
    @PostConstruct
    public 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;

    @PostConstruct
    public 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 version
            sendIQGetWithTimestamp(connection, new Version());

            // query server time
            sendIQGetWithTimestamp(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用户的样子:

1

2

3

我知道,是葡萄牙语。

就是这样。 我们都准备好了。 启动您的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值