diff options
Diffstat (limited to 'sca-java-2.x/branches/2.0/samples/learning-more/binding-comet')
46 files changed, 2712 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/README b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/README new file mode 100644 index 0000000000..57702664d7 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/README @@ -0,0 +1,79 @@ +Tuscany - Learning More - Binding Comet - Autocomplete Webapp +----------------------------------------------------------------- + +This sample demonstrates how Tuscany can expose services via Comet techniques +as well as how to interact with them using Tuscany's javascript API. + +This project contains a service (CountryService) that handles requests asking +for country names starting with a certain prefix. The service implementation +uses a country repository to fetch the necessary data. + +By adding <tuscany:binding.comet/> to a service definition, the Tuscany runtime +will handle the communication between the browser client and the service +implementation using Comet techniques. This enables bidirectional communication +over HTTP, therefore enabling server push. For more information, check +http://en.wikipedia.org/wiki/Comet_(programming). + +The comet binding is using the Atmosphere Framework under the hood to acomodate +as many deployment envorinments as possible. Basically, it checks if the +application server supports Servlet 3.0 falling back to a number of native +comet solutions provided by vendors (Jetty, Tomcat, WebLogic, GlassFish and +others). If none is available, Atmosphere will fallback to blocking IO. + +Invoking comet services can be done using Tuscany's javascript API which simulates +SCA in the browser. It uses the Atmosphere jQuery plugin under the hood. In order +to use it, the following script has to be included in the client page: + <script type="text/javascript" + src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"> + </script> + +The javascript toolkit permits choosing between two comet techniques: HTTP streaming +and long polling. More detailed information about them can be found on the previously +mentioned wikipedia page. + +First, a connect operation has to be issued in order to initiate communication +with the server side using the technique of your choice. This is done using the +connection method as follows: + SCA.TuscanyComet.connect('streaming'); // for HTTP streaming + SCA.TuscanyComet.connect('long-polling'); // for long polling + SCA.TuscanyComet.connect(); // starts with HTTP streaming and falls back to long polling if necessary + +The Tuscany Comet toolkit will inject proxies for all services defined in the composite +that are using binding.comet. All invocation and connection management is handled +under the hood so in order to invoke a comet service, the following should be called: + SCA.CometComponentContext.<service name>.<operation name>(<parameters>, callback); + +The callback parameter is the function that will handle responses received for a +certain service operation. It has a single argument which is the response: + function callback(response) { + // handle response + }; + +Note that the data exchange is automatically handled by the binding, so the +parameters should have the same structure as the data types defined in the method +definition. Also, the response will have the same data type as the return type of +the service method. Objects are passed over the wire in JSON format. + +Another detail worth mentioning is that the binding will use a single HTTP +connection to handle communication between a browser client and all services +defined using binding.comet in the same composite. Requests and responses will get +multiplexed via the same channel and get routed to the appropriate service +implementation, respectively javascript function. This is done in order to avoid +the 2 HTTP connection limit imposed by browsers. For more info, check +http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue. + +In order to run the sample, you can execute "mvn clean install t7:run" which will +start a Tomcat 7 instance automatically or use "mvn package" and deploy the resulting +war to the application server of your choice. + +Next, point your browser at + http://localhost:8080/sample-binding-comet-autocomplete-webapp/ + +You can see how suggestions are being received in real time when characters are +entered in the text field. You can see the persistent HTTP streaming connection +or long polling subsequent connections using the developer tools provided by +your browser. + +The comet binding is an experimental binding so community feedback is much +appreciated. Feel free to send comments or suggestions on the Apache Tuscany +dev mailing list (dev@tuscany.apache.org).
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/pom.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/pom.xml new file mode 100644 index 0000000000..d33a490d2b --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/pom.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<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.apache.tuscany.sca.samples</groupId>
+ <artifactId>tuscany-samples-binding-comet</artifactId>
+ <version>2.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>sample-binding-comet-autocomplete-webapp</artifactId>
+ <packaging>war</packaging>
+ <version>2.0</version>
+ <name>Apache Tuscany SCA Sample binding.comet Real-Time Suggestions Webapp</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-comet-runtime</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-web-api</artifactId>
+ <version>6.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-base-runtime-pom</artifactId>
+ <version>2.0</version>
+ <type>pom</type>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>r09</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.t7mp</groupId>
+ <artifactId>maven-t7-plugin</artifactId>
+ <version>0.9.6</version>
+ <configuration>
+ <webapps>
+ <webappArtifact>
+ <groupId>org.apache.tuscany.sca.samples</groupId>
+ <artifactId>sample-binding-comet-autocomplete-webapp</artifactId>
+ <version>2.0</version>
+ </webappArtifact>
+ </webapps>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Country.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Country.java new file mode 100644 index 0000000000..eedacf01d0 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Country.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.io.Serializable; + +public class Country implements Serializable { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepository.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepository.java new file mode 100644 index 0000000000..12cdfb4235 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepository.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.List; + +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +public interface CountryRepository { + + List<Country> findStartingWith(String text); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepositoryImpl.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepositoryImpl.java new file mode 100644 index 0000000000..57e2d3e214 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryRepositoryImpl.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.oasisopen.sca.annotation.Constructor; +import org.oasisopen.sca.annotation.EagerInit; +import org.oasisopen.sca.annotation.Init; +import org.oasisopen.sca.annotation.Property; +import org.oasisopen.sca.annotation.Scope; +import org.oasisopen.sca.annotation.Service; + +@EagerInit +@Scope("COMPOSITE") +@Service(CountryRepository.class) +public class CountryRepositoryImpl implements CountryRepository { + + private String fileName; + private List<Country> countries; + + @Constructor + public CountryRepositoryImpl(@Property(name = "fileName") String fileName) { + this.fileName = fileName; + countries = new ArrayList<Country>(); + } + + @Init + public void start() { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getClassLoader() + .getResourceAsStream(fileName))); + String line; + while ((line = reader.readLine()) != null) { + if (!line.startsWith("#")) { + Country c = new Country(); + c.setName(line); + countries.add(c); + } + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public List<Country> findStartingWith(String text) { + List<Country> result = new ArrayList<Country>(); + for (Country c : countries) { + if (c.getName().toLowerCase().startsWith(text.toLowerCase())) { + result.add(c); + } + } + return result; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryService.java new file mode 100644 index 0000000000..e916ecb98b --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryService.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.List; + +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +public interface CountryService { + + List<Country> getCountriesStartingWith(String text); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryServiceImpl.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryServiceImpl.java new file mode 100644 index 0000000000..ad0786be59 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/CountryServiceImpl.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.List; + +import org.oasisopen.sca.annotation.Reference; +import org.oasisopen.sca.annotation.Service; + +@Service(CountryService.class) +public class CountryServiceImpl implements CountryService { + + @Reference + protected CountryRepository repository; + + @Override + public List<Country> getCountriesStartingWith(String text) { + return repository.findStartingWith(text); + } +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/resources/countries.txt b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/resources/countries.txt new file mode 100644 index 0000000000..0ce76f8167 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/resources/countries.txt @@ -0,0 +1,211 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +Afghanistan +Albania +Algeria +Andorra +Angola +Antigua & Barbuda +Argentina +Armenia +Australia +Austria +Azerbaijan +Bahamas +Bahrain +Bangladesh +Barbados +Belarus +Belgium +Belize +Benin +Bhutan +Bolivia +Bosnia & Herzegovina +Botswana +Brazil +Brunei +Bulgaria +Burkina Faso +Burundi +Cambodia +Cameroon +Canada +Cape Verde +Central African Republic +Chad +Chile +China +Colombia +Comoros +Congo +Congo Democratic Republic of +Costa Rica +Cote d'Ivoire +Croatia +Cuba +Cyprus +Czech Republic +Denmark +Djibouti +Dominica +Dominican Republic +Ecuador +East Timor +Egypt +El Salvador +Equatorial Guinea +Eritrea +Estonia +Ethiopia +Fiji +Finland +France +Gabon +Gambia +Georgia +Germany +Ghana +Greece +Grenada +Guatemala +Guinea +Guinea-Bissau +Guyana +Haiti +Honduras +Hungary +Iceland +India +Indonesia +Iran +Iraq +Ireland +Israel +Italy +Jamaica +Japan +Jordan +Kazakhstan +Kenya +Kiribati +Korea North +Korea South +Kosovo +Kuwait +Kyrgyzstan +Laos +Latvia +Lebanon +Lesotho +Liberia +Libya +Liechtenstein +Lithuania +Luxembourg +Macedonia +Madagascar +Malawi +Malaysia +Maldives +Mali +Malta +Marshall Islands +Mauritania +Mauritius +Mexico +Micronesia +Moldova +Monaco +Mongolia +Montenegro +Morocco +Mozambique +Myanmar (Burma) +Namibia +Nauru +Nepal +The Netherlands +New Zealand +Nicaragua +Niger +Nigeria +Norway +Oman +Pakistan +Palau +Palestinian State* +Panama +Papua New Guinea +Paraguay +Peru +The Philippines +Poland +Portugal +Qatar +Romania +Russia +Rwanda +St. Kitts & Nevis +St. Lucia +St. Vincent & The Grenadines +Samoa +San Marino +Sao Tome & Principe +Saudi Arabia +Senegal +Serbia +Seychelles +Sierra Leone +Singapore +Slovakia +Slovenia +Solomon Islands +Somalia +South Africa +Spain +Sri Lanka +Sudan +Suriname +Swaziland +Sweden +Switzerland +Syria +Taiwan +Tajikistan +Tanzania +Thailand +Togo +Tonga +Trinidad & Tobago +Tunisia +Turkey +Turkmenistan +Tuvalu +Uganda +Ukraine +United Arab Emirates +United Kingdom +United States of America +Uruguay +Uzbekistan +Vanuatu +Vatican City (Holy See) +Venezuela +Yemen +Zambia +Zimbabwe diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..58630c02ef --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.composite b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.composite new file mode 100644 index 0000000000..f7cee35452 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.composite @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1" + xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" + targetNamespace="http://samples" name="Chat"> + + <component name="CountryServiceComponent"> + <implementation.java + class="org.apache.tuscany.sca.sample.comet.CountryServiceImpl" /> + <service name="CountryService"> + <interface.java interface="org.apache.tuscany.sca.sample.comet.CountryService" /> + <tuscany:binding.comet /> + </service> + <reference name="repository" target="CountryRepositoryComponent" /> + </component> + + <component name="CountryRepositoryComponent"> + <implementation.java + class="org.apache.tuscany.sca.sample.comet.CountryRepositoryImpl" /> + <property name="fileName">countries.txt</property> + </component> + +</composite>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..25b06c457a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:j2ee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3.0.xsd" version="3.0"> + <display-name>Apache Tuscany Stock Comet Sample</display-name> + <filter> + <filter-name>tuscany</filter-name> + <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> + <async-supported>true</async-supported> + </filter> + <filter-mapping> + <filter-name>tuscany</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> +</web-app>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/index.html b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/index.html new file mode 100644 index 0000000000..115ca7bbdb --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/autocomplete-webapp/src/main/webapp/index.html @@ -0,0 +1,69 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<html> + <head> + <title>Apache Tuscany Comet Sample</title> + <!-- Tuscany Comet Javascript Toolkit is dependent on jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script> + <script type="text/javascript" src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"></script> + <script type="text/javascript"> + var user = ""; + + $(document).ready(function() + { + // Tuscany Comet specific API + SCA.TuscanyComet.connect(); + + $("#country").keyup(function() { + var text = $("#country").val(); + if (text != "") { + SCA.CometComponentContext.CountryService.getCountriesStartingWith(text, callback); + } else { + $("#suggestions").html(""); + } + }); + + $("#country").focus(); + }); + + function callback(response) { + var html = '<ul>'; + $.each(response, function(index, country) { + html += '<li>' + country.name + "</li>" + }); + html += '</ul>' + $("#suggestions").html(html); + } + + </script> + </head> + <body> + <h2>Apache Tuscany Comet Sample</h2> + <h3>Real-time suggestions</h3> + <table> + <tr> + <td>Enter a country name</td> + <td><input type="text" id='country'/></td> + </tr> + </table> + </div> + <div id="suggestions"> + </div> + </body> +</html> diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/README b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/README new file mode 100644 index 0000000000..303c63146a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/README @@ -0,0 +1,99 @@ +Tuscany - Learning More - Binding Comet - Chat Webapp +----------------------------------------------------------------- + +This sample demonstrates how Tuscany can expose services via Comet techniques +as well as how to interact with them using Tuscany's javascript toolkit. It +also demonstrates how to push multiple responses for a single request using +SCA callbacks via comet techniques. + +This project contains a service (ChatService) that handles chat operations like +register and postMessage. Once a client is registered it will receive messages +that are sent to the chat room. + +By adding <tuscany:binding.comet/> to a service definition, the Tuscany runtime +will handle the communication between the browser client and the service +implementation using Comet techniques. This enables bidirectional communication +over HTTP, therefore enabling server push. For more information, check +http://en.wikipedia.org/wiki/Comet_(programming). + +The comet binding is using the Atmosphere Framework under the hood to acomodate +as many deployment envorinments as possible. Basically, it checks if the +application server supports Servlet 3.0 falling back to a number of native +comet solutions provided by vendors (Jetty, Tomcat, WebLogic, GlassFish and +others). If none is available, Atmosphere will fallback to blocking IO. + +In order to enable callbacks to push multiple responses, you need to declare the +CometCallback in the service definition as follows: + <interface.java interface="org.apache.tuscany.sca.sample.comet.ChatService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback" /> + <tuscany:binding.comet /> + <callback> + <tuscany:binding.comet /> + </callback> + +The callback object has methods that facilitate sending messages back to the +calling client. It can be injected in the service implementation using the @Callback +annotation. However, the service implementation for this sample has the COMPOSITE +scope so the callback reference has to be obtained from the ComponentContext. + +One requirement that service methods have to meet to enable multiple response +support is that they have to be annotated with @OneWay to enable non-blocking +support. Without it, methods are treated synchronously sending a single response +which is the object returned by the method call. + +Invoking comet services can be done using Tuscany's javascript API which simulates +SCA in the browser. It uses the Atmosphere jQuery plugin under the hood. In order +to use it, the following script has to be included in the client page: + <script type="text/javascript" + src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"> + </script> + +The javascript toolkit permits choosing between two comet techniques: HTTP streaming +and long polling. More detailed information about them can be found on the previously +mentioned wikipedia page. + +First, a connect operation has to be issued in order to initiate communication +with the server side using the technique of your choice. This is done using the +connection method as follows: + SCA.TuscanyComet.connect('streaming'); // for HTTP streaming + SCA.TuscanyComet.connect('long-polling'); // for long polling + SCA.TuscanyComet.connect(); // starts with HTTP streaming and falls back to long polling if necessary + +The Tuscany Comet toolkit will inject proxies for all services defined in the composite +that are using binding.comet. All invocation and connection management is handled +under the hood so in order to invoke a comet service, the following should be called: + SCA.CometComponentContext.<service name>.<operation name>(<parameters>, callback); + +The callback parameter is the function that will handle responses received for a +certain service operation. It has a single argument which is the response: + function callback(response) { + // handle response + }; + +Note that the data exchange is automatically handled by the binding, so parameters +will be mapped to the data types defined in the method definition. Also, the response +will have the same data type as the server side object used to wrap the response. +Objects are passed over the wire in JSON format. + +Another detail worth mentioning is that the binding will use a single HTTP +connection to handle communication between a browser client and all services +defined using binding.comet in the same composite. Requests and responses will get +multiplexed via the same channel and get routed to the appropriate service +implementation, respectively javascript function. This is done in order to avoid +the 2 HTTP connection limit imposed by browsers. For more info, check +http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue. + +In order to run the sample, you can execute "mvn clean install t7:run" which will +start a Tomcat 7 instance automatically or use "mvn package" and deploy the resulting +war to the application server of your choice. + +Next, point your browser at + http://localhost:8080/sample-binding-comet-chat-webapp/ + +You can now chat using multiple tabs or browsers. You can see the persistent HTTP +streaming connection or long polling subsequent connections using the developer tools +provided by your browser. + +The comet binding is an experimental binding so community feedback is much +appreciated. Feel free to send comments or suggestions on the Apache Tuscany +dev mailing list (dev@tuscany.apache.org).
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/pom.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/pom.xml new file mode 100644 index 0000000000..494df712a6 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<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.apache.tuscany.sca.samples</groupId>
+ <artifactId>tuscany-samples-binding-comet</artifactId>
+ <version>2.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>sample-binding-comet-chat-webapp</artifactId>
+ <packaging>war</packaging>
+ <version>2.0</version>
+ <name>Apache Tuscany SCA Sample binding.comet Chat Webapp</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-comet-runtime</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-web-api</artifactId>
+ <version>6.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-base-runtime-pom</artifactId>
+ <version>2.0</version>
+ <type>pom</type>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>r09</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.t7mp</groupId>
+ <artifactId>maven-t7-plugin</artifactId>
+ <version>0.9.6</version>
+ <configuration>
+ <webapps>
+ <webappArtifact>
+ <groupId>org.apache.tuscany.sca.samples</groupId>
+ <artifactId>sample-binding-comet-chat-webapp</artifactId>
+ <version>2.0</version>
+ </webappArtifact>
+ </webapps>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatService.java new file mode 100644 index 0000000000..acb224715a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatService.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +@Callback(CometCallback.class) +@Remotable +public interface ChatService { + + @OneWay + void register(); + + @OneWay + void postMessage(String user, String message); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatServiceImpl.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatServiceImpl.java new file mode 100644 index 0000000000..c4f3241c5b --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/ChatServiceImpl.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.ArrayList; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.binding.comet.runtime.callback.Status; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.annotation.Context; +import org.oasisopen.sca.annotation.Scope; +import org.oasisopen.sca.annotation.Service; + +@Service(ChatService.class) +@Scope("COMPOSITE") +public class ChatServiceImpl implements ChatService { + + @Context + protected ComponentContext context; + + private CopyOnWriteArrayList<CometCallback> clients = new CopyOnWriteArrayList<CometCallback>(); + + @Override + public void postMessage(String user, String message) { + for (CometCallback callback : new ArrayList<CometCallback>(clients)) { + Status status = callback.sendMessage(user + ": " + message); + if (status == Status.CLIENT_DISCONNECTED) { + clients.remove(callback); + } + } + } + + @Override + public void register() { + // saving the callback object during register() method so it will push data back to the client + // using the callback method defined for the register operation in the js when used + clients.add(context.getRequestContext().<CometCallback> getCallback()); + } +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..58630c02ef --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.composite b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.composite new file mode 100644 index 0000000000..c535a38116 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.composite @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://samples" name="Chat"> + + <component name="ChatComponent"> + <implementation.java + class="org.apache.tuscany.sca.sample.comet.ChatServiceImpl" /> + <service name="ChatService"> + <interface.java interface="org.apache.tuscany.sca.sample.comet.ChatService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback" /> + <tuscany:binding.comet /> + <callback> + <tuscany:binding.comet /> + </callback> + </service> + </component> + +</composite>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..25b06c457a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:j2ee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3.0.xsd" version="3.0"> + <display-name>Apache Tuscany Stock Comet Sample</display-name> + <filter> + <filter-name>tuscany</filter-name> + <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> + <async-supported>true</async-supported> + </filter> + <filter-mapping> + <filter-name>tuscany</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> +</web-app>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/index.html b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/index.html new file mode 100644 index 0000000000..1aa79ed0b6 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/chat-webapp/src/main/webapp/index.html @@ -0,0 +1,109 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<html> + <head> + <title>Apache Tuscany Comet Sample</title> + <!-- Tuscany Comet Javascript Toolkit is dependent on jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script> + <script type="text/javascript" src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"></script> + <script type="text/javascript"> + var user = ""; + + $(document).ready(function() + { + $("#chat").hide(); + $("#username").focus(); + + // Tuscany Comet specific API + SCA.TuscanyComet.connect(); + + $("#register").click(function() { + register(messageCallback); + }); + + $("#username").keyup(function(e) { + if(e.keyCode == 13) { + register(messageCallback); + } + }); + + function register(callback) { + SCA.CometComponentContext.ChatService.register(callback); + user = $("#username").val(); + $("#login").hide(); + $("#chat").show(); + $("#message").focus(); + } + + $("#send").click(function() { + postMessage(user, $("#message").val(), postCallback); + }); + + $("#message").keyup(function(e) { + if(e.keyCode == 13) { + postMessage(user, $("#message").val(), postCallback); + } + }); + + function postMessage(user, message, callback) { + SCA.CometComponentContext.ChatService.postMessage(user, message, callback); + $("#message").val(""); + $("#message").focus(); + } + + }); + + // this method is invoked on new messages because the CometCallback object is saved + // during the register call so uses it's callback to push data back + function messageCallback(response) { + var textarea = document.getElementById('textarea'); + textarea.value += response + "\n"; + textarea.scrollTop = textarea.scrollHeight; + } + + function postCallback(response) { + } + + </script> + </head> + <body> + <h2>Apache Tuscany Comet Sample</h2> + <h3>Chat</h3> + <p/> + <div id="login"> + <table> + <tr> + <td>Nickname</td> + <td><input type="text" id='username'/></td> + <td><input type="button" id='register' value='Login'/></td> + </tr> + </table> + </div> + <div id="chat"> + <h3>Server notifications</h3> + <textarea id="textarea" rows="15" cols="30" readonly></textarea> + <table> + <tr> + <td><input type="text" id='message'/></td> + <td><input type="button" id='send' value='Send'/></td> + </tr> + </table> + </div> + </body> +</html> diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pom.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pom.xml new file mode 100644 index 0000000000..2f8193b893 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pom.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca.samples</groupId>
+ <artifactId>tuscany-samples-learning-more</artifactId>
+ <version>2.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>tuscany-samples-binding-comet</artifactId>
+ <packaging>pom</packaging>
+ <name>Apache Tuscany SCA Sample binding.comet</name>
+
+ <profiles>
+ <profile>
+ <id>default</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <modules>
+ <module>autocomplete-webapp</module>
+ <module>weather-webapp</module>
+ <module>pubsub-webapp</module>
+ <module>chat-webapp</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/README b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/README new file mode 100644 index 0000000000..845ff70e58 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/README @@ -0,0 +1,102 @@ +Tuscany - Learning More - Binding Comet - PubSub Webapp +----------------------------------------------------------------- + +This sample demonstrates how Tuscany can expose services via Comet techniques +as well as how to interact with them using Tuscany's javascript toolkit. It +also demonstrates how to push multiple responses for a single request using +SCA callbacks via comet techniques. + +This project contains a component that registers browser clients' interest in a +certain event type. When an event of that type comes in, it notifies all registered +clients. The event processor exposes a service via the websocket binding which +enables server push to clients. Note that Tuscany 2.x doesn't have any conversational +support so this has to be handled at application level by passing ids back and forth +between the client and the server. + +By adding <tuscany:binding.comet/> to a service definition, the Tuscany runtime +will handle the communication between the browser client and the service +implementation using Comet techniques. This enables bidirectional communication +over HTTP, therefore enabling server push. For more information, check +http://en.wikipedia.org/wiki/Comet_(programming). + +The comet binding is using the Atmosphere Framework under the hood to acomodate +as many deployment envorinments as possible. Basically, it checks if the +application server supports Servlet 3.0 falling back to a number of native +comet solutions provided by vendors (Jetty, Tomcat, WebLogic, GlassFish and +others). If none is available, Atmosphere will fallback to blocking IO. + +In order to enable callbacks to push multiple responses, you need to declare the +CometCallback in the service definition as follows: + <interface.java interface="org.apache.tuscany.sca.sample.comet.ChatService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback" /> + <tuscany:binding.comet /> + <callback> + <tuscany:binding.comet /> + </callback> + +The callback object has methods that facilitate sending messages back to the +calling client. It can be injected in the service implementation using the @Callback +annotation. + +One requirement that service methods have to meet to enable multiple response +support is that they have to be annotated with @OneWay to enable non-blocking +support. Without it, methods are treated synchronously sending a single response +which is the object returned by the method call. + +Invoking comet services can be done using Tuscany's javascript API which simulates +SCA in the browser. It uses the Atmosphere jQuery plugin under the hood. In order +to use it, the following script has to be included in the client page: + <script type="text/javascript" + src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"> + </script> + +The javascript toolkit permits choosing between two comet techniques: HTTP streaming +and long polling. More detailed information about them can be found on the previously +mentioned wikipedia page. + +First, a connect operation has to be issued in order to initiate communication +with the server side using the technique of your choice. This is done using the +connection method as follows: + SCA.TuscanyComet.connect('streaming'); // for HTTP streaming + SCA.TuscanyComet.connect('long-polling'); // for long polling + SCA.TuscanyComet.connect(); // starts with HTTP streaming and falls back to long polling if necessary + +The Tuscany Comet toolkit will inject proxies for all services defined in the composite +that are using binding.comet. All invocation and connection management is handled +under the hood so in order to invoke a comet service, the following should be called: + SCA.CometComponentContext.<service name>.<operation name>(<parameters>, callback); + +The callback parameter is the function that will handle responses received for a +certain service operation. It has a single argument which is the response: + function callback(response) { + // handle response + }; + +Note that the data exchange is automatically handled by the binding, so parameters +will be mapped to the data types defined in the method definition. Also, the response +will have the same data type as the server side object used to wrap the response. +Objects are passed over the wire in JSON format. + +Another detail worth mentioning is that the binding will use a single HTTP +connection to handle communication between a browser client and all services +defined using binding.comet in the same composite. Requests and responses will get +multiplexed via the same channel and get routed to the appropriate service +implementation, respectively javascript function. This is done in order to avoid +the 2 HTTP connection limit imposed by browsers. For more info, check +http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue. + +In order to run the sample, you can execute "mvn clean install t7:run" which will +start a Tomcat 7 instance automatically or use "mvn package" and deploy the resulting +war to the application server of your choice. + +Next, point your browser at + http://localhost:8080/sample-binding-comet-chat-webapp/ + +You can now register or unregister for any of a number of events. When an event is fired +on the server side, the browser client will receive a notification which will be displayed +in the page. You can see the persistent HTTP streaming connection or long polling subsequent +connections using the developer tools provided by your browser. + +The comet binding is an experimental binding so community feedback is much +appreciated. Feel free to send comments or suggestions on the Apache Tuscany +dev mailing list (dev@tuscany.apache.org).
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/pom.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/pom.xml new file mode 100644 index 0000000000..0e497e3cb0 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/pom.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<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.apache.tuscany.sca.samples</groupId>
+ <artifactId>tuscany-samples-binding-comet</artifactId>
+ <version>2.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>sample-binding-comet-pubsub-webapp</artifactId>
+ <packaging>war</packaging>
+ <version>2.0</version>
+ <name>Apache Tuscany SCA Sample binding.comet PubSub Webapp</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-comet-runtime</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-web-api</artifactId>
+ <version>6.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-base-runtime-pom</artifactId>
+ <version>2.0</version>
+ <type>pom</type>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>r09</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.t7mp</groupId>
+ <artifactId>maven-t7-plugin</artifactId>
+ <version>0.9.6</version>
+ <configuration>
+ <webapps>
+ <webappArtifact>
+ <groupId>org.apache.tuscany.sca.samples</groupId>
+ <artifactId>sample-binding-comet-pubsub-webapp</artifactId>
+ <version>2.0</version>
+ </webappArtifact>
+ </webapps>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Event.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Event.java new file mode 100644 index 0000000000..bcc6bea7af --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Event.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +public class Event { + + private String id; + private String name; + private String data; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessor.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessor.java new file mode 100644 index 0000000000..838d2f317c --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessor.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.binding.comet.runtime.callback.Status; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.annotation.Context; +import org.oasisopen.sca.annotation.Destroy; +import org.oasisopen.sca.annotation.Scope; +import org.oasisopen.sca.annotation.Service; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; + +@Service({ EventProcessorConsumerService.class, EventProcessorProducerService.class }) +@Scope("COMPOSITE") +public class EventProcessor implements EventProcessorConsumerService, EventProcessorProducerService { + + @Context + protected ComponentContext componentContext; + + private ConcurrentMap<String, CometCallback> clients = new ConcurrentHashMap<String, CometCallback>(); + private Multimap<String, String> eventListeners = Multimaps.synchronizedMultimap(HashMultimap + .<String, String> create()); + + @Override + public void onEvent(String eventName, String eventData) { + // System.out.println("EventProcessor: Received event " + eventName + + // "..."); + List<String> destinations = new ArrayList<String>(); + synchronized (eventListeners) { + destinations.addAll(eventListeners.get(eventName)); + } + Event event = new Event(); + event.setName(eventName); + event.setData(eventData); + for (String registrationId : destinations) { + CometCallback client = clients.get(registrationId); + if (client == null) { + // client has unregistered from this event + synchronized (eventListeners) { + eventListeners.remove(eventName, registrationId); + } + } else { + Status status = client.sendMessage(event); + if (status == Status.CLIENT_DISCONNECTED) { + unregister(registrationId); + } + } + } + } + + @Override + public void register(String eventName) { + String registrationId = UUID.randomUUID().toString(); + CometCallback callback = componentContext.getRequestContext().getCallback(); + clients.put(registrationId, callback); + synchronized (eventListeners) { + eventListeners.put(eventName, registrationId); + } + Event event = new Event(); + event.setId(registrationId); + event.setName(eventName); + event.setData(new Date().toString()); + callback.sendMessage(event); + } + + @Override + public void unregister(String registrationId) { + clients.remove(registrationId); + // unregistration from eventListeners done during onEvent + } + + @Destroy + public void shutdown() { + clients.clear(); + eventListeners.clear(); + clients = null; + eventListeners = null; + } +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorConsumerService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorConsumerService.java new file mode 100644 index 0000000000..c8208e862c --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorConsumerService.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +@Callback(CometCallback.class) +@Remotable +public interface EventProcessorConsumerService { + + @OneWay + void register(String eventName); + + @OneWay + void unregister(String registrationId); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorProducerService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorProducerService.java new file mode 100644 index 0000000000..49d760d171 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/EventProcessorProducerService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +public interface EventProcessorProducerService { + + void onEvent(String eventName, String eventData); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Producer.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Producer.java new file mode 100644 index 0000000000..59307824ce --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Producer.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import org.oasisopen.sca.annotation.Constructor; +import org.oasisopen.sca.annotation.Destroy; +import org.oasisopen.sca.annotation.EagerInit; +import org.oasisopen.sca.annotation.Init; +import org.oasisopen.sca.annotation.Property; +import org.oasisopen.sca.annotation.Reference; +import org.oasisopen.sca.annotation.Scope; + +@EagerInit +@Scope("COMPOSITE") +public class Producer { + + @Reference + protected EventProcessorProducerService eventProcessor; + + private String eventName; + private long frequency; + + private Timer timer = new Timer(); + private Object lock = new Object(); + + @Constructor + public Producer(@Property(name = "eventName") String eventName, @Property(name = "frequency") long frequency) { + System.out.println("Producer: In Constructor with eventName=" + eventName + " and frequency=" + frequency); + this.eventName = eventName; + this.frequency = frequency; + } + + @Init + public void start() { + System.out.println("Producer: In Init..."); + timer.schedule(new TimerTask() { + + @Override + public void run() { +// System.out.println("Producer: Producing " + eventName + " event..."); + synchronized (lock) { + eventProcessor.onEvent(Producer.this.eventName, "Event @ " + new Date()); + } + } + }, 0L, this.frequency); + } + + @Destroy + public void stop() { + synchronized (lock) { + timer.cancel(); + } + timer = null; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..58630c02ef --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.composite b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.composite new file mode 100644 index 0000000000..6479e10e99 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.composite @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://samples" name="Event"> + + <component name="EventProcessorComponent"> + <implementation.java + class="org.apache.tuscany.sca.sample.comet.EventProcessor" /> + <service name="EventProcessorConsumerService"> + <interface.java + interface="org.apache.tuscany.sca.sample.comet.EventProcessorConsumerService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback" /> + <tuscany:binding.comet /> + <callback> + <tuscany:binding.comet /> + </callback> + </service> + <service name="EventProcessorProducerService"> + <interface.java + interface="org.apache.tuscany.sca.sample.comet.EventProcessorProducerService" /> + </service> + </component> + + <component name="SLOWProducerComponent"> + <implementation.java class="org.apache.tuscany.sca.sample.comet.Producer" /> + <reference name="eventProcessor" target="EventProcessorComponent" /> + <property name="eventName">SLOW</property> + <property name="frequency">6000</property> + </component> + + <component name="MODERATEProducerComponent"> + <implementation.java class="org.apache.tuscany.sca.sample.comet.Producer" /> + <reference name="eventProcessor" target="EventProcessorComponent" /> + <property name="eventName">MODERATE</property> + <property name="frequency">3000</property> + </component> + + <component name="FASTProducerComponent"> + <implementation.java class="org.apache.tuscany.sca.sample.comet.Producer" /> + <reference name="eventProcessor" target="EventProcessorComponent" /> + <property name="eventName">FAST</property> + <property name="frequency">1000</property> + </component> + +</composite>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..25b06c457a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:j2ee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3.0.xsd" version="3.0"> + <display-name>Apache Tuscany Stock Comet Sample</display-name> + <filter> + <filter-name>tuscany</filter-name> + <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> + <async-supported>true</async-supported> + </filter> + <filter-mapping> + <filter-name>tuscany</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> +</web-app>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/index.html b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/index.html new file mode 100644 index 0000000000..0488c4cb10 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/pubsub-webapp/src/main/webapp/index.html @@ -0,0 +1,107 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<html> +<head> + <title>Apache Tuscany Comet Sample</title> + <!-- Tuscany Comet Javascript Toolkit is dependent on jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script> + <script type="text/javascript" src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"></script> + <script type="text/javascript"> + $(document).ready(function() + { + // Tuscany Comet specific API + $('#connect').click(function(event) { + /* transport can be : long-polling or streaming */ + SCA.TuscanyComet.connect($('#transport').val()); + $('#connect').val('Switch'); + }); + + + $('#registerEventButton').click(function(event) { + var eventName = $('#registerEventName').val(); + if (registrationIds[eventName] != null) { + alert("Already registered for " + eventName + " events"); + } else { + SCA.CometComponentContext.EventProcessorConsumerService.register(eventName, responseReceived); + } + }); + + $('#unregisterEventButton').click(function(event) { + var eventName = $('#unregisterEventName').val(); + if (registrationIds[eventName] != null) { + SCA.CometComponentContext.EventProcessorConsumerService.unregister(registrationIds[eventName], responseReceived); + registrationIds[eventName] = null; + } else { + alert("Not registered for " + eventName + " events"); + } + }); + + }); + + var registrationIds = {}; + + function responseReceived(event) { + var text = ''; + if (event.id != null) { + // registration notification + registrationIds[event.name] = event.id; + text = "Registered to " + event.name + " with id " + event.id + " at " + event.data; + } else { + // event notification + text = event.name + ": " + event.data; + } + var textarea = $('#textarea'); + $(textarea).val($(textarea).val() + text + "\n"); + $(textarea).scrollTop($(textarea)[0].scrollHeight); + } + + </script> +</head> +<body> + <div id='sidebar'> + <h2>Apache Tuscany Comet Sample</h2> + <label>Select transport</label> <select id="transport"> + <option id="streaming" value="streaming">http streaming</option> + <option id="long-polling" value="long-polling">long-polling</option> + </select> <input id='connect' type='submit' value='Connect' /> + <h3>PubSub for FAST, MODERATE and SLOW events</h3> + <p /> + <table> + <tr> + <td>Event name</td> + <td><input type="text" id='registerEventName' value='FAST' /> + </td> + <td><input type="button" id='registerEventButton' + value='Register' /> + </td> + </tr> + <tr> + <td>Event name</td> + <td><input type="text" id='unregisterEventName' value='FAST' /> + </td> + <td><input type="button" id='unregisterEventButton' + value='Unregister' /> + </td> + </tr> + </table> + <h3>Server notifications</h3> + <textarea id="textarea" rows="15" cols="80" readonly></textarea> + </div> +</body> +</html> diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/README b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/README new file mode 100644 index 0000000000..dc69bcf6fc --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/README @@ -0,0 +1,100 @@ +Tuscany - Learning More - Binding Comet - Weather Monitor Webapp +----------------------------------------------------------------- + +This sample demonstrates how Tuscany can expose services via Comet techniques +as well as how to interact with them using Tuscany's javascript toolkit. It +also demonstrates how to push multiple responses for a single request using +SCA callbacks via comet techniques. + +This project contains multiple services that once called will push notifications +to the client regarding certain weather parameters according to the location of +the user. Of course, the service implementation is a mock that generates random +numbers at a fixed interval of time as weather parameters. + +By adding <tuscany:binding.comet/> to a service definition, the Tuscany runtime +will handle the communication between the browser client and the service +implementation using Comet techniques. This enables bidirectional communication +over HTTP, therefore enabling server push. For more information, check +http://en.wikipedia.org/wiki/Comet_(programming). + +The comet binding is using the Atmosphere Framework under the hood to acomodate +as many deployment envorinments as possible. Basically, it checks if the +application server supports Servlet 3.0 falling back to a number of native +comet solutions provided by vendors (Jetty, Tomcat, WebLogic, GlassFish and +others). If none is available, Atmosphere will fallback to blocking IO. + +In order to enable callbacks to push multiple responses, you need to declare the +CometCallback in the service definition as follows: + <interface.java interface="org.apache.tuscany.sca.sample.comet.ChatService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback" /> + <tuscany:binding.comet /> + <callback> + <tuscany:binding.comet /> + </callback> + +The callback object has methods that facilitate sending messages back to the +calling client. It can be injected in the service implementation using the @Callback +annotation. + +One requirement that service methods have to meet to enable multiple response +support is that they have to be annotated with @OneWay to enable non-blocking +support. Without it, methods are treated synchronously sending a single response +which is the object returned by the method call. + +Invoking comet services can be done using Tuscany's javascript API which simulates +SCA in the browser. It uses the Atmosphere jQuery plugin under the hood. In order +to use it, the following script has to be included in the client page: + <script type="text/javascript" + src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"> + </script> + +The javascript toolkit permits choosing between two comet techniques: HTTP streaming +and long polling. More detailed information about them can be found on the previously +mentioned wikipedia page. + +First, a connect operation has to be issued in order to initiate communication +with the server side using the technique of your choice. This is done using the +connection method as follows: + SCA.TuscanyComet.connect('streaming'); // for HTTP streaming + SCA.TuscanyComet.connect('long-polling'); // for long polling + SCA.TuscanyComet.connect(); // starts with HTTP streaming and falls back to long polling if necessary + +The Tuscany Comet toolkit will inject proxies for all services defined in the composite +that are using binding.comet. All invocation and connection management is handled +under the hood so in order to invoke a comet service, the following should be called: + SCA.CometComponentContext.<service name>.<operation name>(<parameters>, callback); + +The callback parameter is the function that will handle responses received for a +certain service operation. It has a single argument which is the response: + function callback(response) { + // handle response + }; + +Note that the data exchange is automatically handled by the binding, so parameters +will be mapped to the data types defined in the method definition. Also, the response +will have the same data type as the server side object used to wrap the response. +Objects are passed over the wire in JSON format. + +Another detail worth mentioning is that the binding will use a single HTTP +connection to handle communication between a browser client and all services +defined using binding.comet in the same composite. Requests and responses will get +multiplexed via the same channel and get routed to the appropriate service +implementation, respectively javascript function. This is done in order to avoid +the 2 HTTP connection limit imposed by browsers. For more info, check +http://www.openajax.org/runtime/wiki/The_Two_HTTP_Connection_Limit_Issue. + +In order to run the sample, you can execute "mvn clean install t7:run" which will +start a Tomcat 7 instance automatically or use "mvn package" and deploy the resulting +war to the application server of your choice. + +Next, point your browser at + http://localhost:8080/sample-binding-comet-weather-webapp/ + +You can now set a location and register for various weather parameters. Notifications +will be pushed to the browser when weather parameters change. You can see the persistent +HTTP streaming connection or long polling subsequent connections using the developer +tools provided by your browser. + +The comet binding is an experimental binding so community feedback is much +appreciated. Feel free to send comments or suggestions on the Apache Tuscany +dev mailing list (dev@tuscany.apache.org).
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/pom.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/pom.xml new file mode 100644 index 0000000000..25c0094aa9 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/pom.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<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.apache.tuscany.sca.samples</groupId>
+ <artifactId>tuscany-samples-binding-comet</artifactId>
+ <version>2.0</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>sample-binding-comet-weather-webapp</artifactId>
+ <packaging>war</packaging>
+ <version>2.0</version>
+ <name>Apache Tuscany SCA Sample binding.comet Weather Monitor Webapp</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-binding-comet-runtime</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax</groupId>
+ <artifactId>javaee-web-api</artifactId>
+ <version>6.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-base-runtime-pom</artifactId>
+ <version>2.0</version>
+ <type>pom</type>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.t7mp</groupId>
+ <artifactId>maven-t7-plugin</artifactId>
+ <version>0.9.6</version>
+ <configuration>
+ <webapps>
+ <webappArtifact>
+ <groupId>org.apache.tuscany.sca.samples</groupId>
+ <artifactId>sample-binding-comet-weather-webapp</artifactId>
+ <version>2.0</version>
+ </webappArtifact>
+ </webapps>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Helper.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Helper.java new file mode 100644 index 0000000000..eecc6044ea --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/Helper.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.Date; +import java.util.Random; + +public final class Helper { + + public static int randomInt(final int max) { + return (new Random(new Date().getTime()).nextInt(100)); + } + + private Helper() { + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/HumidityService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/HumidityService.java new file mode 100644 index 0000000000..7145e30e03 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/HumidityService.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.sample.comet.model.Location; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +@Callback(CometCallback.class) +public interface HumidityService { + + @OneWay + void getHumidity(Location location); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationService.java new file mode 100644 index 0000000000..a53fac5ed1 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationService.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.sample.comet.model.Location; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +@Callback(CometCallback.class) +public interface PrecipitationService { + + @OneWay + void getPrecipitation(Location location); + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationServiceImpl.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationServiceImpl.java new file mode 100644 index 0000000000..2c064a3ae6 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/PrecipitationServiceImpl.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.binding.comet.runtime.callback.Status; +import org.apache.tuscany.sca.sample.comet.model.Location; +import org.apache.tuscany.sca.sample.comet.model.Response; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.Service; + +@Service(PrecipitationService.class) +public class PrecipitationServiceImpl implements PrecipitationService { + + @Callback + protected CometCallback client; + + @Override + public void getPrecipitation(final Location location) { + new Timer().scheduleAtFixedRate(new TimerTask() { + + @Override + public void run() { + Response response = new Response(); + response.setDate(new Date()); + response.setData(Helper.randomInt(100) + "%"); + Status status = client.sendMessage(response); + if (status == Status.CLIENT_DISCONNECTED) { + System.out.println("Client disconnected from PrecipitationService."); + this.cancel(); + } + } + }, 0L, 1000L); + } +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureHumidityServiceImpl.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureHumidityServiceImpl.java new file mode 100644 index 0000000000..4227667e7f --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureHumidityServiceImpl.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.binding.comet.runtime.callback.Status; +import org.apache.tuscany.sca.sample.comet.model.Location; +import org.apache.tuscany.sca.sample.comet.model.Response; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.Service; + +@Service({ TemperatureService.class, HumidityService.class }) +public class TemperatureHumidityServiceImpl implements TemperatureService, HumidityService { + + @Callback + protected CometCallback callback; + + @Override + public void getHumidity(final Location location) { + new Timer().scheduleAtFixedRate(new TimerTask() { + + @Override + public void run() { + final Response response = new Response(); + response.setDate(new Date()); + response.setData(Helper.randomInt(90) + "%"); + Status status = callback.sendMessage(response); + if (status == Status.CLIENT_DISCONNECTED) { + System.out.println("Client disconnected from HumidityService."); + this.cancel(); + } + } + }, 0L, 5000L); + } + + @Override + public void getTemperature(final Location location, final int scale) { + new Timer().scheduleAtFixedRate(new TimerTask() { + + @Override + public void run() { + final Response response = new Response(); + response.setDate(new Date()); + final String data = "" + Helper.randomInt(scale == TemperatureService.CELSIUS ? 40 : 150); + response.setData(data); + Status status = callback.sendMessage(response); + if (status == Status.CLIENT_DISCONNECTED) { + System.out.println("Client disconnected from TemperatureService."); + this.cancel(); + } + } + }, 0L, 3000L); + } + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureService.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureService.java new file mode 100644 index 0000000000..83afae696f --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/TemperatureService.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet; + +import org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback; +import org.apache.tuscany.sca.sample.comet.model.Location; +import org.oasisopen.sca.annotation.Callback; +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +@Callback(CometCallback.class) +public interface TemperatureService { + + public static final int CELSIUS = 1; + public static final int FAHRENHEIT = 2; + + @OneWay + void getTemperature(Location location, int scale); + +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Location.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Location.java new file mode 100644 index 0000000000..ff2da3a360 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Location.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet.model; + +public class Location { + + private String city; + private String country; + + public String getCity() { + return this.city; + } + + public void setCity(final String city) { + this.city = city; + } + + public String getCountry() { + return this.country; + } + + public void setCountry(final String country) { + this.country = country; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Response.java b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Response.java new file mode 100644 index 0000000000..aaa23f0b8a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/java/org/apache/tuscany/sca/sample/comet/model/Response.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.tuscany.sca.sample.comet.model; + +import java.util.Date; + +public class Response { + + private Date date; + private String data; + + public Date getDate() { + return this.date; + } + + public void setDate(final Date date) { + this.date = date; + } + + public String getData() { + return this.data; + } + + public void setData(final String data) { + this.data = data; + } + +} diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..58630c02ef --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0
+
diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.composite b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.composite new file mode 100644 index 0000000000..20d25fe527 --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.composite @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1" + targetNamespace="http://samples" + name="Weather"> + + <component name="c1"> + <implementation.java class="org.apache.tuscany.sca.sample.comet.TemperatureHumidityServiceImpl"/> + <service name="TemperatureService"> + <interface.java interface="org.apache.tuscany.sca.sample.comet.TemperatureService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback"/> + <tuscany:binding.comet/> + <callback> + <tuscany:binding.comet/> + </callback> + </service> + <service name="HumidityService"> + <interface.java interface="org.apache.tuscany.sca.sample.comet.HumidityService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback"/> + <tuscany:binding.comet/> + <callback> + <tuscany:binding.comet/> + </callback> + </service> + </component> + + + <component name="c2"> + <implementation.java class="org.apache.tuscany.sca.sample.comet.PrecipitationServiceImpl"/> + <service name="PrecipitationService"> + <interface.java interface="org.apache.tuscany.sca.sample.comet.PrecipitationService" + callbackInterface="org.apache.tuscany.sca.binding.comet.runtime.callback.CometCallback"/> + <tuscany:binding.comet/> + <callback> + <tuscany:binding.comet/> + </callback> + </service> + </component> + +</composite>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.xml b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..25b06c457a --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:j2ee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3.0.xsd" version="3.0"> + <display-name>Apache Tuscany Stock Comet Sample</display-name> + <filter> + <filter-name>tuscany</filter-name> + <filter-class>org.apache.tuscany.sca.host.webapp.TuscanyServletFilter</filter-class> + <async-supported>true</async-supported> + </filter> + <filter-mapping> + <filter-name>tuscany</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + <welcome-file-list> + <welcome-file>index.html</welcome-file> + </welcome-file-list> +</web-app>
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/index.html b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/index.html new file mode 100644 index 0000000000..6c3cf7ab5c --- /dev/null +++ b/sca-java-2.x/branches/2.0/samples/learning-more/binding-comet/weather-webapp/src/main/webapp/index.html @@ -0,0 +1,159 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. +--> +<html> + <head> + <title>Apache Tuscany Comet Sample</title> + <!-- Tuscany Comet Javascript Toolkit is dependent on jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script> + <script type="text/javascript" src="tuscany-comet-js/org.apache.tuscany.sca.CometComponentContext.js"></script> + <script type="text/javascript"> + $(document).ready(function() + { + // Initialization + var location = new Object(); + location.city = null; + location.country = null; + + $('#locationButton').attr('disabled', 'disabled'); + $('#tempCButton').attr('disabled', 'disabled'); + $('#tempFButton').attr('disabled', 'disabled'); + $('#humButton').attr('disabled', 'disabled'); + $('#precipButton').attr('disabled', 'disabled'); + + $('#locationButton').click(function(event) { + location.city = $('#city').val(); + location.country = $('#country').val(); + $('#locationButton').val('Switch location'); + $('#tempCButton').removeAttr('disabled'); + $('#tempFButton').removeAttr('disabled'); + $('#humButton').removeAttr('disabled'); + $('#precipButton').removeAttr('disabled'); + $('#tempCText').text('N/A'); + $('#tempCDate').text(''); + $('#tempFText').text('N/A'); + $('#tempFDate').text(''); + $('#humText').text('N/A'); + $('#humDate').text(''); + $('#precipText').text('N/A'); + $('#precipDate').textContent(''); + }); + + // Tuscany Comet specific API + $('#connect').click(function(event) { + /* transport can be : long-polling or streaming */ + SCA.TuscanyComet.connect($('#transport').val()); + $('#connect').val('Switch'); + $('#locationButton').removeAttr('disabled'); + }); + + + $('#tempCButton').click(function(event) { + SCA.CometComponentContext.TemperatureService.getTemperature(location, 1, updateTempC); + $('#tempCButton').removeAttr('disabled'); + }); + + $('#tempFButton').click(function(event) { + SCA.CometComponentContext.TemperatureService.getTemperature(location, 2, updateTempF); + $('#tempFButton').removeAttr('disabled'); + }); + + $('#humButton').click(function(event) { + SCA.CometComponentContext.HumidityService.getHumidity(location, updateHum); + $('#humButton').removeAttr('disabled'); + }); + + $('#precipButton').click(function(event) { + SCA.CometComponentContext.PrecipitationService.getPrecipitation(location, updatePrecip); + $('#precipButton').removeAttr('disabled'); + }); + }); + + function updateTempC(response) { + $('#tempCText').text(response.data); + $('#tempCDate').text(response.date); + } + + function updateTempF(response) { + $('#tempFText').text(response.data); + $('#tempFDate').text(response.date); + } + + function updateHum(response) { + $('#humText').text(response.data); + $('#humDate').text(response.date); + } + + function updatePrecip(response) { + $('#precipText').text(response.data); + $('#precipDate').text(response.date); + } + </script> + </head> + <body> + <div id='sidebar'> + <h2>Apache Tuscany Comet Sample</h2> + <label>Select transport</label> + <select id="transport"> + <option id="streaming" value="streaming">http streaming</option> + <option id="long-polling" value="long-polling">long-polling</option> + </select> + <input id='connect' type='submit' value='Connect'/> + <h3>Weather Monitor</h3> + <p/> + <table> + <tr> + <td>City</td> + <td><input type="text" id='city' value='Brasov'/></td> + </tr> + <tr> + <td>Country</td> + <td><input type="text" id ='country' value='Romania'/></td> + </tr> + </table> + <input type="button" id='locationButton' value='Set location'/> + <p/> + <table> + <tr> + <th align="left">Temperature (Celsius):</th> + <td><span id='tempCText'>N/A</span></td> + <td><input type='button' id='tempCButton' value="Update"/></td> + <td><span id='tempCDate'></span> + </tr> + <tr> + <th align="left">Temperature (Fahrenheit):</th> + <td><span id='tempFText'>N/A</span></td> + <td><input type='button' id='tempFButton' value="Update"/></td> + <td><span id='tempFDate'></span> + </tr> + <tr> + <th align="left">Humidity:</th> + <td><span id='humText'>N/A</span></td> + <td><input type='button' id='humButton' value="Update"/></td> + <td><span id='humDate'></span> + </tr> + <tr> + <th align="left">Precipitation probability:</th> + <td><span id='precipText'>N/A</span></td> + <td><input type='button' id='precipButton' value="Update"/></td> + <td><span id='precipDate'></span> + </tr> + </table> + </div> + </body> +</html> |