Commits

Andy Moncsek committed 4f25885

add JacpFX Twitter/WebSocket example (initial not ready), cleanup

Comments (0)

Files changed (53)

Domain/src/main/java/org/jacp/jee/entity/Query.java

+/*
+ * Copyright (c) 2013, Andy Moncsek, inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ *    the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
+ *    promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jacp.jee.entity;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 13.03.13
+ * Time: 13:57
+ * To change this template use File | Settings | File Templates.
+ */
+public class Query {
+    private final String query;
+
+    public Query(final String query){
+            this.query = query;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+}

EAR-TwitterWebsocket/pom.xml

+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.jacp.jee</groupId>
+        <artifactId>JEE7-websocket</artifactId>
+        <version>1.0</version>
+    </parent>
+    <artifactId>EAR-TwitterWebsocket</artifactId>
+    <packaging>ear</packaging>
+    <name>EAR-TwitterWebsocket</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-ear-plugin</artifactId>
+                <version>2.8</version>
+                <configuration>
+                    <version>6</version>
+                    <modules>
+                        <jarModule>
+                            <groupId>${project.groupId}</groupId>
+                            <artifactId>Domain</artifactId>
+                            <bundleDir>/lib</bundleDir>
+                        </jarModule>
+                        <webModule>
+                            <groupId>${project.groupId}</groupId>
+                            <artifactId>WebClient-TwitterWebsocket</artifactId>
+                        </webModule>
+                    </modules>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>Domain</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>WebClient-TwitterWebsocket</artifactId>
+            <version>${project.version}</version>
+            <type>war</type>
+        </dependency>
+    </dependencies>
+</project>

EAR-TwitterWebsocket/src/main/application/META-INF/glassfish-resources.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions //EN"
+        "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
+<resources>
+
+    <jdbc-resource jndi-name="jdbc/messageDS" pool-name="jdbc/newsAppDSPool"/>
+
+    <jdbc-connection-pool name="jdbc/newsAppDSPool" datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
+                          max-pool-size="5" pool-resize-quantity="1" res-type="javax.sql.DataSource"
+                          statement-timeout-in-seconds="60" steady-pool-size="0">
+        <property name="dataBaseName" value="NewsDB"/>
+        <property name="User" value="APP"/>
+        <property name="Password" value="APP"/>
+        <property name="connectionAttributes" value=";create=true"/>
+        <property name="driverType" value="4"/>
+    </jdbc-connection-pool>
+
+</resources>

EAR-TwitterWebsocket/src/main/java/org/jacp/jee/App.java

+package org.jacp.jee;
+
+/**
+ * Hello world!
+ */
+public class App {
+    public static void main(String[] args) {
+        System.out.println("Hello World!");
+    }
+}

EAR-TwitterWebsocket/src/test/java/org/jacp/jee/AppTest.java

+package org.jacp.jee;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+        extends TestCase {
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest(String testName) {
+        super(testName);
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite() {
+        return new TestSuite(AppTest.class);
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp() {
+        assertTrue(true);
+    }
+}

JacpFXSSETwitterClient/src/main/java/org/jacp/twitter/components/QueryView.java

 import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
 import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
 import org.jacp.twitter.entities.Clear;
-import org.jacp.twitter.entities.Query;
+import org.jacp.jee.entity.Query;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;

JacpFXSSETwitterClient/src/main/java/org/jacp/twitter/entities/Query.java

-/*
- * Copyright (c) 2013, Andy Moncsek, inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided
- * that the following conditions are met:
- *
- *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
- *    the following disclaimer in the documentation and/or other materials provided with the distribution.
- *
- *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
- *    promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.jacp.twitter.entities;
-
-/**
- * Created with IntelliJ IDEA.
- * User: ady
- * Date: 13.03.13
- * Time: 13:57
- * To change this template use File | Settings | File Templates.
- */
-public class Query {
-    private final String query;
-
-    public Query(final String query){
-            this.query = query;
-    }
-
-    public String getQuery() {
-        return query;
-    }
-}

JacpFXTwitterWebsocketClient/pom.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.jacp.jee</groupId>
+        <artifactId>JEE7-websocket</artifactId>
+        <version>1.0</version>
+    </parent>
+    <artifactId>JacpFXTwitterWebsocketClient</artifactId>
+    <packaging>jar</packaging>
+    <name>JacpFXTwitterWebsocketClient</name>
+    <url>http://maven.apache.org</url>
+    <repositories>
+        <repository>
+            <id>jacp</id>
+            <url>http://developer.ahcp.de/nexus/content/repositories/jacp</url>
+        </repository>
+    </repositories>
+    <developers>
+        <developer>
+            <id>amo</id>
+            <name>Andy Moncsek</name>
+            <email>amo.ahcp@gmail.com</email>
+        </developer>
+        <developer>
+            <id>pete</id>
+            <name>Patrick Symmangk</name>
+            <email>pete.ahcp@gmail.com</email>
+        </developer>
+    </developers>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>2.3</version>
+                <executions>
+                    <execution>
+                        <id>copy-dependencies</id>
+                        <phase>package</phase>
+                        <configuration>
+                            <includeScope>runtime</includeScope>
+                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>true</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <excludeArtifactIds>javafx,log4j</excludeArtifactIds>
+                        </configuration>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.7</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <configuration>
+                            <target xmlns:fx="javafx:com.sun.javafx.tools.ant">
+                                <property name="applet.width" value="1024"/>
+                                <property name="applet.height" value="600"/>
+                                <property name="application.title" value="JacpFX-Quickstart"/>
+                                <property name="application.vendor" value="JacpFX"/>
+                                <manifestclasspath property="manifest.classpath"
+                                                   jarfile="${project.build.directory}/${project.build.finalName}">
+                                    <classpath>
+                                        <path id="build.classpath">
+                                            <fileset dir="${project.build.directory}/lib">
+                                                <include name="*.jar"/>
+                                            </fileset>
+                                        </path>
+                                    </classpath>
+                                </manifestclasspath>
+
+                                <taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
+                                         uri="javafx:com.sun.javafx.tools.ant" classpathref="maven.plugin.classpath"/>
+
+                                <fx:application id="${project.name}" name="${project.name}"
+                                                mainClass="org.jacp.twitter.main.ApplicationLauncher"
+                                                preloaderClass="org.jacp.twitter.main.ApplicationPreloader"/>
+                                <!-- create jar file -->
+                                <fx:jar destfile="${project.build.directory}/${project.build.finalName}.jar">
+                                    <fx:application refid="${project.name}"/>
+                                    <manifest>
+                                        <attribute name="Class-Path" value="${manifest.classpath}"/>
+                                    </manifest>
+                                    <fileset dir="${project.build.outputDirectory}"/>
+                                </fx:jar>
+
+                                <fx:resources id="appRes">
+                                    <fx:fileset dir="${project.build.directory}" includes="*.jar"/>
+                                    <fx:fileset dir="${project.build.directory}" includes="lib/*.jar"/>
+                                </fx:resources>
+
+                                <!-- sign jar
+
+                                <signjar keyStore="${basedir}\keystore.jks"
+                                         destdir="${project.build.directory}"
+                                         alias="..." storePass="..." keyPass="...">
+                                    <fileset dir="${project.build.directory}" includes="*.jar"/>
+                                    <fileset dir="${project.build.directory}" includes="lib/*.jar"/>
+                                </signjar>
+                                -->
+
+                                <!-- create executeables use: nativeBundles="all" to create native executeables-->
+                                <fx:deploy width="${applet.width}" height="${applet.height}"
+                                           outdir="${project.build.directory}/deploy" embedJNLP="true"
+                                           outfile="${application.title}">
+
+                                    <fx:application refId="${project.name}"/>
+                                    <fx:resources refid="appRes"/>
+                                    <fx:platform javafx="${javafx.version}+">
+                                        <fx:jvmarg value="-Xms128m"/>
+                                        <fx:jvmarg value="-Xmx256m"/>
+                                    </fx:platform>
+                                    <fx:info title="${application.title}"
+                                             vendor="${application.vendor}"/>
+                                    <!-- Request elevated permissions -->
+                                    <fx:permissions elevated="true"/>
+                                </fx:deploy>
+
+                            </target>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>com.oracle</groupId>
+                        <artifactId>ant-javafx</artifactId>
+                        <version>${javafx.version}</version>
+                        <systemPath>${java.home}/../lib/ant-javafx.jar</systemPath>
+                        <scope>system</scope>
+                    </dependency>
+                    <dependency>
+                        <groupId>com.oracle</groupId>
+                        <artifactId>javafx</artifactId>
+                        <version>${javafx.version}</version>
+                        <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
+                        <scope>system</scope>
+                    </dependency>
+                </dependencies>
+            </plugin>
+
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>com.oracle</groupId>
+            <artifactId>javafx</artifactId>
+            <version>2.2</version>
+            <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
+            <scope>system</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacp.project</groupId>
+            <artifactId>JACP.API</artifactId>
+            <version>${jacp.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacp.project</groupId>
+            <artifactId>JACP.JavaFX</artifactId>
+            <version>${jacp.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacp.project</groupId>
+            <artifactId>JACP.JavaFXSpring</artifactId>
+            <version>${jacp.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacp.project</groupId>
+            <artifactId>JACP.JavaFXControls</artifactId>
+            <version>${jacp.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring.version}</version>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring.version}</version>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <version>${spring.version}</version>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-expression</artifactId>
+            <version>${spring.version}</version>
+            <type>jar</type>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.16</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>Domain</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.tyrus</groupId>
+            <artifactId>tyrus-client</artifactId>
+            <version>${tyrusWebsocket.version}</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+    </dependencies>
+</project>

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/callbacks/SSEEndpoint.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [SSEEndpoint.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.callbacks;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import javafx.event.Event;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.CallbackComponent;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AStatefulCallbackComponent;
+import org.jacp.jee.entity.TwitterResult;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Logger;
+
+
+/**
+ * A Stateful JacpFX component.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@CallbackComponent(id = "id003", name = "statefulCallback", active = true)
+public class SSEEndpoint extends AStatefulCallbackComponent {
+//    private Client client;
+//    private EventSource eventSource;
+    private final Logger log = Logger.getLogger(SSEEndpoint.class
+            .getName());
+
+    @Override
+    public Object handleAction(final IAction<Event, Object> arg0) {
+        return null;
+    }
+
+
+
+    @OnStart
+    public void init() {
+//        this.log.info("SSEEndpoint start");
+//        SslConfigurator sslConfig = SslConfigurator.newInstance()
+//                .trustStoreFile("NONE")
+//                .keyStoreFile("NONE");
+//
+//        client = ClientBuilder.newBuilder().sslContext(sslConfig.createSSLContext()).build();
+//        final javax.ws.rs.client.WebTarget webTarget = client.target(getURI());
+//        eventSource = new EventSource(webTarget) {
+//            @Override
+//            public void onEvent(InboundEvent inboundEvent) {
+//                //get the JSON data and parse it
+//                Gson parser = new GsonBuilder()
+//                        .setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create();
+//                try {
+//                    log.info("got message");
+//                    TwitterResult result=  parser.fromJson(inboundEvent.getData(String.class,
+//                                MediaType.APPLICATION_JSON_TYPE), TwitterResult.class);
+//                    log.info("send message");
+//                    getActionListener("id001",result).performAction(null);
+//                } catch (IOException e) {
+//                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+//                }
+//
+//            }
+//        };
+    }
+
+
+
+
+    @OnTearDown
+    public void cleanup() {
+//        eventSource.close();
+//        client.close();
+        this.log.info("SSEEndpoint stop");
+
+    }
+
+    private URI getURI() {
+        try {
+            //return new URI("http", null, "192.168.32.130", 80, "/WebClient-SSE/twittersse", null, null);
+           return new URI("http", null, "localhost", 8080, "/WebClient-SSE/twittersse", null, null);
+        } catch (URISyntaxException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/components/QueryView.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [ComponentRight.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.components;
+
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.geometry.Insets;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.*;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.Component;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AFXComponent;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+import org.jacp.twitter.entities.Clear;
+import org.jacp.twitter.entities.Query;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ResourceBundle;
+import java.util.logging.Logger;
+
+/**
+ * A simple JacpFX FXML UI component
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@Component(defaultExecutionTarget = "Ptop", id = "id002", name = "componentRight", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
+public class QueryView extends AFXComponent {
+    private final static String TARGET_URI = "http://localhost:8080/WebClient-SSE";
+    private final Logger log = Logger.getLogger(QueryView.class
+            .getName());
+
+
+    @Override
+    /**
+     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
+     */
+    public Node handleAction(final IAction<Event, Object> action) {
+           if(action.getLastMessage() instanceof Query) {
+               Query query = (Query) action.getLastMessage();
+
+
+           }
+        return null;
+    }
+
+    @Override
+    /**
+     * The postHandleAction method runs always in the main application thread.
+     */
+    public Node postHandleAction(final Node arg0,
+                                 final IAction<Event, Object> action) {
+        // runs in FX application thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            return createUI();
+        }
+        return null;
+    }
+
+    private Node createUI() {
+        final AnchorPane anchor = AnchorPaneBuilder.create()
+                .styleClass("roundedAnchorPaneFX").build();
+
+        HBox hbox = new HBox();
+        hbox.setPadding(new Insets(15, 12, 15, 12));
+        hbox.setSpacing(15);
+        final Label label = new Label("TwitterQuery");
+        final TextField textField = new TextField();
+        textField.setMinWidth(100);
+        final Button button = new Button("OK");
+        button.setOnAction(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(ActionEvent actionEvent) {
+                getActionListener(new Query(textField.getText())).performAction(actionEvent);
+                getActionListener("id001",new Clear()).performAction(actionEvent);
+
+            }
+        });
+        hbox.getChildren().addAll(label,textField,button);
+
+        AnchorPane.setTopAnchor(hbox, 25.0);
+        AnchorPane.setRightAnchor(hbox, 25.0);
+        AnchorPane.setLeftAnchor(hbox, 25.0);
+
+        anchor.getChildren().addAll(hbox);
+
+        GridPane.setHgrow(anchor, Priority.ALWAYS);
+        GridPane.setVgrow(anchor, Priority.ALWAYS);
+
+        return anchor;
+    }
+
+    @OnStart
+    /**
+     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
+     * @param arg0
+     * @param resourceBundle
+     */
+    public void onStartComponent(final FXComponentLayout arg0,
+                                 final ResourceBundle resourceBundle) {
+        this.log.info("run on start of ComponentRight ");
+
+    }
+
+    @OnTearDown
+    /**
+     * The @OnTearDown annotations labels methods executed when the component is set to inactive
+     * @param arg0
+     */
+    public void onTearDownComponent(final FXComponentLayout arg0) {
+        this.log.info("run on tear down of ComponentRight ");
+
+    }
+
+
+
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/components/TweetView.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [TweetView.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.components;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.Event;
+import javafx.scene.Node;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.*;
+import javafx.util.Callback;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.Component;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.javafx.rcp.component.AFXComponent;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+import org.jacp.jee.entity.Tweet;
+import org.jacp.jee.entity.TwitterResult;
+import org.jacp.twitter.entities.Clear;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.logging.Logger;
+
+/**
+ * A simple JacpFX UI component
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@Component(defaultExecutionTarget = "PMain", id = "id001", name = "componentLeft", active = true, resourceBundleLocation = "bundles.languageBundle", localeID = "en_US")
+public class TweetView extends AFXComponent {
+    private AnchorPane pane;
+    private ObservableList<Tweet> tweets = FXCollections.observableArrayList();
+    private final Logger log = Logger.getLogger(TweetView.class.getName());
+
+
+    @Override
+    /**
+     * The handleAction method always runs outside the main application thread. You can create new nodes, execute long running tasks but you are not allowed to manipulate existing nodes here.
+     */
+    public Node handleAction(final IAction<Event, Object> action) {
+        // runs in worker thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            return this.createUI();
+        }
+        return null;
+    }
+
+    @Override
+    /**
+     * The postHandleAction method runs always in the main application thread.
+     */
+    public Node postHandleAction(final Node arg0,
+                                 final IAction<Event, Object> action) {
+        // runs in FX application thread
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+            this.pane = (AnchorPane) arg0;
+        } else if (action.getLastMessage() instanceof TwitterResult) {
+            TwitterResult result = (TwitterResult) action.getLastMessage();
+            if (!result.getResults().isEmpty()) {
+                tweets.addAll(result.getResults());
+                Collections.sort(tweets);
+            }
+        } else if(action.getLastMessage() instanceof Clear){
+            tweets.clear();
+        }
+        return this.pane;
+    }
+
+    @OnStart
+    /**
+     * The @OnStart annotation labels methods executed when the component switch from inactive to active state
+     * @param arg0
+     */
+    public void onStartComponent(final FXComponentLayout arg0,
+                                 final ResourceBundle resourceBundle) {
+        this.log.info("run on start of TweetView ");
+    }
+
+    @OnTearDown
+    /**
+     * The @OnTearDown annotations labels methods executed when the component is set to inactive
+     * @param arg0
+     */
+    public void onTearDownComponent(final FXComponentLayout arg0) {
+        this.log.info("run on tear down of TweetView ");
+
+    }
+
+    /**
+     * create the UI on first call
+     *
+     * @return
+     */
+    private Node createUI() {
+        final AnchorPane anchor = AnchorPaneBuilder.create()
+                .styleClass("roundedAnchorPaneFX").build();
+
+        TableView table = new TableView();
+        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
+        table.getColumns().addAll(createColumns());
+        table.setItems(tweets);
+
+        AnchorPane.setTopAnchor(table, 25.0);
+        AnchorPane.setRightAnchor(table, 25.0);
+        AnchorPane.setLeftAnchor(table, 25.0);
+
+        anchor.getChildren().addAll(table);
+
+        GridPane.setHgrow(anchor, Priority.ALWAYS);
+        GridPane.setVgrow(anchor, Priority.ALWAYS);
+
+        return anchor;
+    }
+
+    private List<TableColumn> createColumns() {
+        TableColumn imageView = new TableColumn("image");
+        imageView.setMinWidth(60);
+        imageView.setCellValueFactory(
+                new PropertyValueFactory<Tweet, String>("profile_image_url"));
+        imageView.setCellFactory(new Callback<TableColumn<Tweet, String>, TableCell<Tweet, String>>() {
+
+            @Override
+            public TableCell<Tweet, String> call(TableColumn<Tweet, String> tweetStringTableColumn) {
+                return new TableCell<Tweet, String>() {
+                    @Override
+                    public void updateItem(String item, boolean empty) {
+                        if (item!=null) {
+                            HBox box = new HBox();
+                            box.setSpacing(10);
+                            VBox vbox = new VBox();
+                            ImageView imageview = new ImageView();
+                            imageview.setFitHeight(50);
+                            imageview.setFitWidth(50);
+                            imageview.setImage(new Image(item, true));
+                            box.getChildren().addAll(imageview, vbox);
+                            setGraphic(box);
+                        }
+                    }
+                };
+                  //To change body of implemented methods use File | Settings | File Templates.
+            }
+        });
+        TableColumn nameView = new TableColumn("name");
+        nameView.setMinWidth(100);
+        nameView.setCellValueFactory(
+                new PropertyValueFactory<Tweet, String>("from_user"));
+        TableColumn messageView = new TableColumn("message");
+        messageView.setMinWidth(500);
+        messageView.setCellValueFactory(
+                new PropertyValueFactory<Tweet, String>("text"));
+        return Arrays.asList(imageView, nameView, messageView);
+    }
+
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/entities/Clear.java

+/*
+ * Copyright (c) 2013, Andy Moncsek, inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ *    the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
+ *    promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jacp.twitter.entities;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 13.03.13
+ * Time: 14:01
+ * To change this template use File | Settings | File Templates.
+ */
+public class Clear {
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/entities/Query.java

+/*
+ * Copyright (c) 2013, Andy Moncsek, inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
+ *    the following disclaimer in the documentation and/or other materials provided with the distribution.
+ *
+ *    Neither the name of Andy Moncsek, inc. nor the names of its contributors may be used to endorse or
+ *    promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.jacp.twitter.entities;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 13.03.13
+ * Time: 13:57
+ * To change this template use File | Settings | File Templates.
+ */
+public class Query {
+    private final String query;
+
+    public Query(final String query){
+            this.query = query;
+    }
+
+    public String getQuery() {
+        return query;
+    }
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/entities/User.java

+package org.jacp.twitter.entities;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: ady
+ * Date: 06.03.13
+ * Time: 11:48
+ * To change this template use File | Settings | File Templates.
+ */
+public class User {
+    private final String userName;
+
+    public User(final String userName) {
+        this.userName = userName;
+    }
+
+    public String getUserName() {
+        return this.userName;
+    }
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/main/ApplicationLauncher.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [ApplicationLauncher.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.main;
+
+import javafx.application.Application;
+import javafx.scene.Scene;
+import javafx.scene.image.Image;
+import javafx.stage.Stage;
+import org.jacp.project.launcher.AFXSpringLauncher;
+
+import java.net.URL;
+import java.util.logging.Logger;
+
+/**
+ * The application launcher containing the main method
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class ApplicationLauncher extends AFXSpringLauncher {
+    private static final Logger log = Logger.getLogger(ApplicationLauncher.class
+            .getName());
+    public static final String[] STYLES = new String[2];
+    private static final String[] STYLE_FILES = {"/styles/style_light.css", "/styles/style_dark.css"};
+    /// binary style sheets created while deployment
+    private static final String[] BINARY_FILES = {"/styles/style_light.bss", "/styles/style_dark.bss"};
+
+    public ApplicationLauncher() {
+        super("main.xml");
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(final String[] args) {
+        Application.launch(args);
+    }
+
+    @Override
+    public void postInit(final Stage stage) {
+        initStyles();
+        stage.setMinHeight(580);
+        stage.setMinWidth(800);
+        final Scene scene = stage.getScene();
+        stage.getIcons().add(new Image("images/icons/JACP_512_512.png"));
+        // add style sheet
+        scene.getStylesheets().add(STYLES[0]);
+    }
+
+    private static void initStyles() {
+        for (int i = 0; i < 2; i++) {
+            URL res = ApplicationLauncher.class.getResource(BINARY_FILES[i]);
+            if (res == null)
+                res = ApplicationLauncher.class.getResource(STYLE_FILES[i]);
+            STYLES[i] = res.toExternalForm();
+            log.info("found: " + STYLES[i] + " stylesheet");
+        }
+
+    }
+
+
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/main/ApplicationPreloader.java

+package org.jacp.twitter.main;
+
+import javafx.animation.FadeTransition;
+import javafx.application.Preloader;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.Scene;
+import javafx.scene.control.ProgressBar;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.BorderPaneBuilder;
+import javafx.stage.Stage;
+import javafx.util.Duration;
+
+/**
+ * The application Preloader. It is just a simple splash screen on application
+ * init. The preloader shows up only when execute the package.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class ApplicationPreloader extends Preloader {
+    private ProgressBar bar;
+    private Stage stage;
+    private boolean isEmbedded = false;
+
+    public void start(Stage stage) throws Exception {
+        isEmbedded = (stage.getWidth() > 0);
+        this.stage = stage;
+        stage.setScene(createPreloaderScene());
+        stage.show();
+    }
+
+    @Override
+    public void handleProgressNotification(ProgressNotification pn) {
+        bar.setProgress(pn.getProgress());
+    }
+
+    @Override
+    public void handleStateChangeNotification(StateChangeNotification evt) {
+        if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
+            if (isEmbedded && stage.isShowing()) {
+                // fade out, hide stage at the end of animation
+                final FadeTransition ft = new FadeTransition(
+                        Duration.millis(3000), stage.getScene().getRoot());
+                ft.setFromValue(1.0);
+                ft.setToValue(0.0);
+                final Stage s = stage;
+                final EventHandler<ActionEvent> eh = new EventHandler<ActionEvent>() {
+                    public void handle(ActionEvent t) {
+                        s.hide();
+                    }
+                };
+                ft.setOnFinished(eh);
+                ft.play();
+            } else {
+                stage.hide();
+            }
+        }
+    }
+
+    private Scene createPreloaderScene() {
+        bar = new ProgressBar();
+        final BorderPane p = BorderPaneBuilder
+                .create()
+                .center(new ImageView(new Image(this.getClass()
+                        .getResourceAsStream("/images/jacp-splash.png"))))
+                .bottom(bar).build();
+        return new Scene(p, 412, 279);
+    }
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/perspectives/PerspectiveOne.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [PerspectiveOne.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.perspectives;
+
+import javafx.event.Event;
+import javafx.fxml.FXML;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import org.jacp.api.action.IAction;
+import org.jacp.api.annotations.OnStart;
+import org.jacp.api.annotations.OnTearDown;
+import org.jacp.api.annotations.Perspective;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.componentLayout.PerspectiveLayout;
+import org.jacp.javafx.rcp.perspective.AFXPerspective;
+import org.jacp.javafx.rcp.util.FXUtil.MessageUtil;
+
+import java.util.ResourceBundle;
+
+/**
+ * A simple perspective defining a split pane
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+@Perspective(id = "id01", name = "perspectiveOne", viewLocation = "/fxml/perspectiveOne.fxml", resourceBundleLocation = "bundles.languageBundle")
+public class PerspectiveOne extends AFXPerspective {
+    @FXML
+    private GridPane gridPaneLeft;
+    @FXML
+    private GridPane gridPaneRight;
+
+    @Override
+    public void handlePerspective(final IAction<Event, Object> action,
+                                  final PerspectiveLayout perspectiveLayout) {
+        if (action.getLastMessage().equals(MessageUtil.INIT)) {
+
+            GridPane.setVgrow(perspectiveLayout.getRootComponent(),
+                    Priority.ALWAYS);
+            GridPane.setHgrow(perspectiveLayout.getRootComponent(),
+                    Priority.ALWAYS);
+
+            // register left panel
+            perspectiveLayout.registerTargetLayoutComponent("Ptop",
+                    this.gridPaneLeft);
+            // register main panel
+            perspectiveLayout.registerTargetLayoutComponent("PMain",
+                    this.gridPaneRight);
+
+        }
+
+    }
+
+    @OnStart
+    /**
+     * @OnStart annotated method will be executed when component is activated.
+     * @param layout
+     * @param resourceBundle
+     */
+    public void onStartPerspective(final FXComponentLayout layout,
+                                   final ResourceBundle resourceBundle) {
+
+    }
+
+    @OnTearDown
+    /**
+     * @OnTearDown annotated method will be executed when component is deactivated.
+     * @param arg0
+     */
+    public void onTearDownPerspective(final FXComponentLayout arg0) {
+        // remove toolbars and menu entries when close perspective
+
+    }
+
+}

JacpFXTwitterWebsocketClient/src/main/java/org/jacp/twitter/workbench/Workbench.java

+/************************************************************************
+ *
+ * Copyright (C) 2010 - 2012
+ *
+ * [Workbench.java]
+ * AHCP Project (http://jacp.googlecode.com)
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ *
+ ************************************************************************/
+package org.jacp.twitter.workbench;
+
+import javafx.event.ActionEvent;
+import javafx.event.Event;
+import javafx.event.EventHandler;
+import javafx.geometry.Pos;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuItem;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+import org.jacp.api.action.IAction;
+import org.jacp.api.componentLayout.IWorkbenchLayout;
+import org.jacp.javafx.rcp.componentLayout.FXComponentLayout;
+import org.jacp.javafx.rcp.components.menuBar.JACPMenuBar;
+import org.jacp.javafx.rcp.components.modalDialog.JACPModalDialog;
+import org.jacp.javafx.rcp.controls.optionPane.JACPDialogButton;
+import org.jacp.javafx.rcp.controls.optionPane.JACPDialogUtil;
+import org.jacp.javafx.rcp.controls.optionPane.JACPOptionPane;
+import org.jacp.javafx.rcp.workbench.AFXWorkbench;
+import org.jacp.twitter.main.ApplicationLauncher;
+
+/**
+ * A simple JacpFX workbench. Define basic UI settings like size, menus and
+ * toolbars here.
+ *
+ * @author <a href="mailto:amo.ahcp@gmail.com"> Andy Moncsek</a>
+ */
+public class Workbench extends AFXWorkbench {
+    private Stage stage;
+
+    @Override
+    public void handleInitialLayout(final IAction<Event, Object> action,
+                                    final IWorkbenchLayout<Node> layout, final Stage stage) {
+        layout.setWorkbenchXYSize(1024, 600);
+        layout.setStyle(StageStyle.DECORATED);
+        layout.setMenuEnabled(true);
+        this.stage = stage;
+
+    }
+
+    @Override
+    public void postHandle(final FXComponentLayout layout) {
+        final JACPMenuBar menu = layout.getMenu();
+        final Menu menuFile = new Menu("File");
+        final Menu menuStyles = new Menu("Styles");
+        menuFile.getItems().add(getHelpItem());
+        // add style selection
+        for (int i = 0; i < ApplicationLauncher.STYLES.length; i++) {
+            menuStyles.getItems().add(getStyle(i));
+        }
+
+        menu.getMenus().addAll(menuFile, menuStyles);
+
+
+        // show windowButtons
+        menu.registerWindowButtons();
+    }
+
+
+    private MenuItem getStyle(final int count) {
+        final MenuItem itemHelp = new MenuItem(count == 0 ? "Light" : "Dark");
+        itemHelp.setOnAction(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(final ActionEvent arg0) {
+                final Scene scene = Workbench.this.stage.getScene();
+                // index 0 is always the default JACP style
+                scene.getStylesheets().remove(1);
+                scene.getStylesheets().add(ApplicationLauncher.STYLES[count]);
+
+            }
+        });
+        return itemHelp;
+    }
+
+    private MenuItem getHelpItem() {
+        final MenuItem itemHelp = new MenuItem("Help");
+        itemHelp.setOnAction(new EventHandler<ActionEvent>() {
+            @Override
+            public void handle(final ActionEvent arg0) {
+                // create a modal dialog
+                final JACPOptionPane dialog = JACPDialogUtil.createOptionPane(
+                        "Help", "Add some help text ");
+                dialog.setDefaultButton(JACPDialogButton.NO);
+                dialog.setDefaultCloseButtonOrientation(Pos.CENTER_RIGHT);
+                dialog.setOnYesAction(new EventHandler<ActionEvent>() {
+
+                    @Override
+                    public void handle(final ActionEvent arg0) {
+                        JACPModalDialog.getInstance().hideModalMessage();
+                    }
+                });
+                JACPModalDialog.getInstance().showModalMessage(dialog);
+
+            }
+        });
+        return itemHelp;
+    }
+
+}

JacpFXTwitterWebsocketClient/src/main/resources/bundles/languageBundle_de.properties

+send=Senden 
+name=Name
+street=Strasse
+country=Land
+fxmlComp=FXML Komponente
+fxmlCompBottom=FXML Komponente unten
+javafxComp=JavaFX Komponente
+javafxCompTop=JavaFX Komponente oben
+description=Caht Fenster
+registeredUsers = angemeldete Nutzer

JacpFXTwitterWebsocketClient/src/main/resources/bundles/languageBundle_en.properties

+send=Send 
+name=name
+street=street
+country=country
+fxmlComp=FXML Component
+fxmlCompBottom=FXML Component Bottom
+javafxComp=JavaFX Component
+javafxCompTop=JavaFX Component Top
+description=Chat window
+registeredUsers = registered users

JacpFXTwitterWebsocketClient/src/main/resources/fxml/ComponentRightFXML.fxml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.net.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.image.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?import javafx.scene.shape.*?>
+<?import javafx.scene.text.*?>
+
+<BorderPane id="BorderPane" xmlns:fx="http://javafx.com/fxml">
+    <center>
+        <AnchorPane fx:id="details" styleClass="roundedAnchorPaneFX">
+            <children>
+                <AnchorPane fx:id="descriptionArea" prefHeight="428" prefWidth="160.0" styleClass="roundedAnchorPane"
+                            AnchorPane.topAnchor="50" AnchorPane.leftAnchor="21.0" AnchorPane.rightAnchor="20.0">
+                    <children>
+                        <Label id="descriptionLabel" layoutX="10.0" layoutY="8.0" styleClass="propLabel"
+                               text="%description"/>
+                        <TextArea fx:id="descriptionValue" prefHeight="127.0" prefWidth="374.19"
+                                  styleClass="descriptionValue" text="" AnchorPane.bottomAnchor="20.0"
+                                  AnchorPane.leftAnchor="12.0" AnchorPane.rightAnchor="12.0" AnchorPane.topAnchor="24.0"
+                                  editable="false"/>
+                    </children>
+                </AnchorPane>
+                <TextField id="synopsis" fx:id="message" prefHeight="38.0" prefWidth="573.0"
+                           styleClass="descriptionValue" text="" AnchorPane.leftAnchor="21"
+                           AnchorPane.rightAnchor="20.5" AnchorPane.bottomAnchor="50.0"/>
+                <Button id="button1" fx:id="sendButton" alignment="BOTTOM_LEFT" text="%send" AnchorPane.rightAnchor="20"
+                        AnchorPane.bottomAnchor="12" onAction="#handleSend"/>
+            </children>
+        </AnchorPane>
+    </center>
+</BorderPane>

JacpFXTwitterWebsocketClient/src/main/resources/fxml/LoginDialog.fxml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.geometry.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.image.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+<?import javafx.scene.text.*?>
+
+<GridPane hgap="14.0" maxHeight="150.0" maxWidth="300.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0"
+          prefWidth="300.0" vgap="20.0" styleClass="jacp-option-pane" xmlns:fx="http://javafx.com/fxml">
+    <children>
+        <VBox maxHeight="+Infinity" maxWidth="+Infinity" minHeight="-Infinity" spacing="7.0" GridPane.columnIndex="1"
+              GridPane.rowIndex="0">
+            <children>
+                <Label fx:id="messageLabel" text="Login" textAlignment="LEFT" wrapText="true">
+                    <font>
+                        <Font name="System Bold" size="13.0"/>
+                    </font>
+                </Label>
+                <TextField prefWidth="200.0" fx:id="login"/>
+            </children>
+        </VBox>
+        <HBox maxHeight="-Infinity" maxWidth="+Infinity" minHeight="-Infinity" minWidth="-Infinity"
+              GridPane.columnIndex="1" GridPane.rowIndex="1">
+            <children>
+                <Pane maxWidth="+Infinity" HBox.hgrow="ALWAYS"/>
+                <HBox id="HBox" fx:id="okParent" alignment="CENTER">
+                    <children>
+                        <Button minWidth="80.0" mnemonicParsing="false" text="Ok" HBox.hgrow="NEVER" fx:id="loginButton"
+                                onAction="#login">
+                            <HBox.margin>
+                                <Insets left="14.0"/>
+                            </HBox.margin>
+                        </Button>
+                    </children>
+                </HBox>
+            </children>
+        </HBox>
+    </children>
+    <columnConstraints>
+        <ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity"/>
+        <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="+Infinity" minWidth="-Infinity"/>
+    </columnConstraints>
+    <padding>
+        <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/>
+    </padding>
+    <rowConstraints>
+        <RowConstraints maxHeight="+Infinity" minHeight="-Infinity" valignment="CENTER" vgrow="ALWAYS"/>
+        <RowConstraints maxHeight="-Infinity" minHeight="-Infinity" vgrow="NEVER"/>
+    </rowConstraints>
+</GridPane>

JacpFXTwitterWebsocketClient/src/main/resources/fxml/perspectiveOne.fxml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import java.lang.*?>
+<?import java.util.*?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.paint.*?>
+
+<BorderPane id="BorderPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" xmlns:fx="http://javafx.com/fxml">
+  <center>
+    <SplitPane id="splitPaneHorizontal1" cache="true" cacheHint="SPEED" dividerPositions="0.15066889632107024" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="100.0" minWidth="200.0" orientation="VERTICAL" prefHeight="600.0" prefWidth="800.0" styleClass="hsplitpane">
+      <items>
+        <GridPane fx:id="gridPaneLeft" cache="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
+          <columnConstraints>
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
+          </columnConstraints>
+          <rowConstraints>
+            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
+          </rowConstraints>
+        </GridPane>
+        <GridPane fx:id="gridPaneRight">
+          <columnConstraints>
+            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
+          </columnConstraints>
+          <rowConstraints>
+            <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
+          </rowConstraints>
+        </GridPane>
+      </items>
+    </SplitPane>
+  </center>
+</BorderPane>
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_128_128.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_16_16.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_256_256.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_32_32.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_512_512.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/icons/JACP_64_64.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/jacp-splash.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/texture_dark.png

Added
New image
Add a comment to this file

JacpFXTwitterWebsocketClient/src/main/resources/images/texture_light.png

Added
New image

JacpFXTwitterWebsocketClient/src/main/resources/log4j.properties

+log4j.rootCategory=off, stdout, A
+log4j.logger.org.jacp.twitter=off
+# stdout is set to be a ConsoleAppender using a PatternLayout.
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) \u2013 %m%n
+# Log gets appended to the file created daily.
+
+log4j.appender.A=org.apache.log4j.DailyRollingFileAppender
+
+# The file will be stored in the path given in this command.
+
+log4j.appender.A.File=l4j.log
+
+log4j.appender.A.layout=org.apache.log4j.PatternLayout
+
+# Pattern to output the caller's file name, line number, and date and time.
+
+log4j.appender.A.layout.ConversionPattern=%d{MM-dd@HH:mm:ss} %5p %t (%F:%L) \u2013 %m%n
+

JacpFXTwitterWebsocketClient/src/main/resources/main.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+	http://www.springframework.org/schema/context 
+	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <context:component-scan base-package="org.jacp.twitter"/>
+    <context:annotation-config/>
+
+    <bean id="workbench" class="org.jacp.twitter.workbench.Workbench">
+        <property name="perspectives">
+            <list>
+                <ref bean="perspectiveOne"/>
+            </list>
+        </property>
+    </bean>
+
+
+    <bean id="perspectiveOne" class="org.jacp.twitter.perspectives.PerspectiveOne">
+        <property name="subcomponents">
+            <list>
+                <ref bean="tweetView"/>
+                <ref bean="queryView"/>
+                <ref bean="sseEndpoint"/>
+            </list>
+        </property>
+    </bean>
+
+
+    <bean id="tweetView" class="org.jacp.twitter.components.TweetView"/>
+    <bean id="queryView" class="org.jacp.twitter.components.QueryView"/>
+
+    <bean id="sseEndpoint" class="org.jacp.twitter.callbacks.SSEEndpoint"/>
+
+</beans>

JacpFXTwitterWebsocketClient/src/main/resources/server.properties

+server = ws://localhost:8080/WebClient-Websocket/chat

JacpFXTwitterWebsocketClient/src/main/resources/styles/style_dark.css

+.root {
+    -fx-font-family: "System";
+    -fx-font-size: 12.703703703703704px;
+    -fx-base: #555555;
+    -fx-hover-base: #555555;
+    -fx-background: #555555;
+    -fx-focus-color: #AAAAAA;
+    -fx-text-box-border: #AAAAAA;
+    -fx-text-base-color: #F0F0F0;
+    -fx-control-inner-background: #555555;
+
+}
+
+/* Description textArea */
+
+.descriptionValue {
+    -fx-font: 1.166666em "System";
+    -fx-background-color: -fx-base;
+    -fx-effect: innershadow(three-pass-box, gray, 1, 1, 0, 0);
+    -fx-text-fill: -fx-text-base-color;
+}
+
+.descriptionValue:focused {
+    -fx-background-color: -fx-focus-color, transparent, -fx-base;
+    -fx-effect: innershadow(three-pass-box, gray, 1, 1, 0, 0);
+}
+
+.descriptionValue:hover {
+    -fx-background-color: -fx-focus-color, -fx-text-box-border, -fx-focus-color;
+}
+
+/* Anchor Pane, Label and Textfield in Properties area */
+
+.propLabel {
+    -fx-text-fill: -fx-text-base-color;
+    -fx-font: 0.833333em "System";
+}