svn commit: r1750557 - in /ofbiz/trunk: ./ framework/catalina/lib/ framework/catalina/src/org/ofbiz/catalina/container/ specialpurpose/example/ specialpurpose/example/servicedef/ specialpurpose/example/src/org/ofbiz/example/ specialpurpose/example/weba...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1750557 - in /ofbiz/trunk: ./ framework/catalina/lib/ framework/catalina/src/org/ofbiz/catalina/container/ specialpurpose/example/ specialpurpose/example/servicedef/ specialpurpose/example/src/org/ofbiz/example/ specialpurpose/example/weba...

jleroux@apache.org
Author: jleroux
Date: Tue Jun 28 18:50:04 2016
New Revision: 1750557

URL: http://svn.apache.org/viewvc?rev=1750557&view=rev
Log:
A patch from Amardeep Singh Jhajj for "Add websocket support in OFBiz" https://issues.apache.org/jira/browse/OFBIZ-7073
It also contains a slightly modified patch from Amardeep Singh Jhajj for "WebSocket Example - Push Notifications" - https://issues.apache.org/jira/browse/OFBIZ-7467 - It's adding working example (in example application) of WebSocket support

I tried to use websockets in OFBiz. I simply added tomcat-embed-websocket.jar in catalina lib and created one webapp for websocket and also added server endpoint class.
It didn't work. After that, I tried the same thing with plain j2ee application with embedded tomcat. It worked there.
I researched on above issue in OFBiz and got the reason. Websockets implementation need jar scanning enabled and it is currently disabled in OFBiz. Below is the code snippet of disabling jar scan from CatalinaContainer.java:

    JarScanner jarScanner = context.getJarScanner();
    if (jarScanner instanceof StandardJarScanner) {
        StandardJarScanner standardJarScanner = (StandardJarScanner) jarScanner;
        standardJarScanner.setScanClassPath(false);
    }

Jar scanning enabling increase OFBiz server startup time upto couples of minutes (in my case, it took approx 8 minutes), so we don't want this much of startup time for OFBiz.
I got the following document where I found the reason why websocket is not working if scanning disabled.

    https://wiki.apache.org/tomcat/HowTo/FasterStartUp

Here tips are given to decrease the startup time. This tips also include disabling of jar scanning.
We can say disabling jar scanning is right approach because if we enable it then scanner will scan all the jars loaded in OFBiz startup that we don't want.
But, If we want websockets working then we have to enable jar scanning.
For enabling jar scanning, we need below code:

    standardJarScanner.setScanClassPath(true); // Will increase server startup time.

Solution: We can add filter on jar scanning. It will allow only some kind of jars only. For example: jars having websockets endpoints. I am attaching patch for the same here.
I added filter like if jar name string contains "discoverable" word then only it will be considered for jar scan. We can change jar name of our jars using build.xml to make it discoverable for jar scanning.
For example: I have added my websocket endpoint class in "specialpurpose/ecommerce/src" and changed the "name" property in build.xml of ecommerce component from "ofbiz-ecommerce"
to "ofbiz-ecommerce-discoverable". Here is the code snippet from build.xml:

    <property name="name" value="ofbiz-ecommerce-discoverable"/>

This change will create the jar with name "ofbiz-ecommerce-discoverable.jar" in "ecommerce/build/lib/".
Now created jar will be scanned in jar scanner as its name contains "discoverable" word in it.
This change will not increase server start up time more than couple of seconds (in my case, it just two seconds). So scanning time totally depends on the list of jars scanned.
Conclusion: We can use websocket support with the help of jar filters.


jleroux: I committed the 2 patches at the same time because the changes in .classpath and the LICENSE files were in the example patch for OFBIZ-7467.

I also slightly modified the example patch in order to provide an example where no sync issues are possible by using a Collections.synchronizedSet for the javax.websocket.Session Set. I also used synchronized loops as it's requested for synchronizedSet where it's used. I know it rather symbolic in the example component but it will remember developers about the possible sync issue.

Added:
    ofbiz/trunk/framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar   (with props)
    ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java   (with props)
    ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java   (with props)
    ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java   (with props)
    ofbiz/trunk/specialpurpose/example/webapp/example/js/
    ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js   (with props)
Modified:
    ofbiz/trunk/.classpath
    ofbiz/trunk/LICENSE
    ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/CatalinaContainer.java
    ofbiz/trunk/specialpurpose/example/build.xml
    ofbiz/trunk/specialpurpose/example/servicedef/secas.xml
    ofbiz/trunk/specialpurpose/example/servicedef/services.xml
    ofbiz/trunk/specialpurpose/example/webapp/example/WEB-INF/web.xml
    ofbiz/trunk/specialpurpose/example/widget/example/CommonScreens.xml

Modified: ofbiz/trunk/.classpath
URL: http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/.classpath (original)
+++ ofbiz/trunk/.classpath Tue Jun 28 18:50:04 2016
@@ -204,6 +204,7 @@
  <classpathentry kind="lib" path="framework/catalina/lib/tomcat-8.0.33-tomcat-util.jar"/>
  <classpathentry kind="lib" path="framework/catalina/lib/tomcat-extras-8.0.33-tomcat-juli-adapters.jar"/>
  <classpathentry kind="lib" path="framework/catalina/lib/tomcat-extras-8.0.33-tomcat-juli.jar"/>
+ <classpathentry kind="lib" path="framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar"/>
  <classpathentry kind="lib" path="framework/base/lib/xstream-1.4.9.jar"/>
  <classpathentry kind="output" path="bin"/>
 </classpath>

Modified: ofbiz/trunk/LICENSE
URL: http://svn.apache.org/viewvc/ofbiz/trunk/LICENSE?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/LICENSE (original)
+++ ofbiz/trunk/LICENSE Tue Jun 28 18:50:04 2016
@@ -94,6 +94,7 @@ framework/catalina/lib/tomcat-8.0.33-tom
 framework/catalina/lib/tomcat-8.0.33-tomcat-util.jar
 framework/catalina/lib/tomcat-extras-8.0.33-tomcat-juli.jar
 framework/catalina/lib/tomcat-extras-8.0.33-tomcat-juli-adapters.jar
+framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar
 framework/entity/lib/commons-dbcp2-2.1.jar
 framework/entity/lib/jdbc/derby-10.11.1.1.jar
 framework/geronimo/lib/geronimo-transaction-3.1.1.jar

Added: ofbiz/trunk/framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar?rev=1750557&view=auto
==============================================================================
Binary file - no diff available.

Propchange: ofbiz/trunk/framework/catalina/lib/tomcat-embed-websocket-8.0.33.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/CatalinaContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/CatalinaContainer.java?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/CatalinaContainer.java (original)
+++ ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/CatalinaContainer.java Tue Jun 28 18:50:04 2016
@@ -560,7 +560,8 @@ public class CatalinaContainer implement
         JarScanner jarScanner = context.getJarScanner();
         if (jarScanner instanceof StandardJarScanner) {
             StandardJarScanner standardJarScanner = (StandardJarScanner) jarScanner;
-            standardJarScanner.setScanClassPath(false);
+            standardJarScanner.setJarScanFilter(new FilterJars());
+            standardJarScanner.setScanClassPath(true);
         }
 
         context.setJ2EEApplication(J2EE_APP);

Added: ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java?rev=1750557&view=auto
==============================================================================
--- ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java (added)
+++ ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java Tue Jun 28 18:50:04 2016
@@ -0,0 +1,16 @@
+package org.ofbiz.catalina.container;
+
+import org.apache.tomcat.JarScanType;
+import org.apache.tomcat.JarScanFilter;
+
+final class FilterJars implements JarScanFilter {
+
+    @Override
+    public boolean check(final JarScanType jarScanType, final String jarName) {
+        if (jarName.contains("discoverable")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

Propchange: ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/framework/catalina/src/org/ofbiz/catalina/container/FilterJars.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/specialpurpose/example/build.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/build.xml?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/build.xml (original)
+++ ofbiz/trunk/specialpurpose/example/build.xml Tue Jun 28 18:50:04 2016
@@ -27,7 +27,7 @@ under the License.
 
     <property environment="env"/>
     <property name="desc" value="Example Component"/>
-    <property name="name" value="ofbiz-example"/>
+    <property name="name" value="ofbiz-example-discoverable"/>
     <property name="ofbiz.home.dir" value="../.."/>
     <property name="src.dir" value="src"/>
     <property name="dtd.dir" value="dtd"/>
@@ -36,6 +36,7 @@ under the License.
 
     <path id="local.class.path">
         <fileset dir="${lib.dir}" includes="*.jar"/>
+        <fileset dir="../../framework/catalina/lib" includes="*.jar"/>
         <fileset dir="../../framework/base/lib" includes="*.jar"/>
         <fileset dir="../../framework/base/lib/commons" includes="*.jar"/>
         <fileset dir="../../framework/base/lib/j2eespecs" includes="*.jar"/>

Modified: ofbiz/trunk/specialpurpose/example/servicedef/secas.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/servicedef/secas.xml?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/servicedef/secas.xml (original)
+++ ofbiz/trunk/specialpurpose/example/servicedef/secas.xml Tue Jun 28 18:50:04 2016
@@ -31,4 +31,14 @@ under the License.
         <action service="createExampleStatus" mode="sync"/>
     </eca>
     -->
+    <!-- Send push notification on create example -->
+    <eca service="updateExample" event="global-commit-post-run">
+        <set field-name="message" value="Example is updated"/>
+        <action service="sendExamplePushNotifications" mode="sync"/>
+    </eca>
+    <!-- Send push notification on update example -->
+    <eca service="createExample" event="global-commit-post-run">
+        <set field-name="message" value="New example created"/>
+        <action service="sendExamplePushNotifications" mode="sync"/>
+    </eca>
 </service-eca>

Modified: ofbiz/trunk/specialpurpose/example/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/servicedef/services.xml?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/servicedef/services.xml (original)
+++ ofbiz/trunk/specialpurpose/example/servicedef/services.xml Tue Jun 28 18:50:04 2016
@@ -126,4 +126,11 @@ under the License.
              location="component://example/minilang/example/ExampleServices.xml" invoke="testCreateExampleService">
         <implements service="testServiceInterface"/>
     </service>
+    <!-- Send push notification service -->
+    <service name="sendExamplePushNotifications" engine="java"
+                location="org.ofbiz.example.ExampleServices" invoke="sendExamplePushNotifications" auth="true">
+        <attribute name="exampleId" mode="IN" type="String" optional="true"></attribute>
+        <attribute name="message" mode="IN" type="String" optional="true"></attribute>
+        <attribute name="successMessage" mode="IN" type="String" optional="true"></attribute>
+    </service>
 </services>

Added: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java?rev=1750557&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java (added)
+++ ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java Tue Jun 28 18:50:04 2016
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.ofbiz.example;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+import javax.websocket.Session;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.service.DispatchContext;
+import org.ofbiz.service.ServiceUtil;
+
+public class ExampleServices {
+    public static final String module = ExampleServices.class.getName();
+
+    public static Map<String, Object> sendExamplePushNotifications(DispatchContext dctx, Map<String, ? extends Object> context) {
+        String exampleId = (String) context.get("exampleId");
+        String message = (String) context.get("message");
+        Set<Session> clients = (Set<Session>) ExampleWebSockets.getClients();
+        try {
+            synchronized (clients) {
+                for (Session client : clients) {
+                    client.getBasicRemote().sendText(message + ": " + exampleId);
+                }
+            }
+        } catch (IOException e) {
+            Debug.logError(e.getMessage(), module);
+        }
+        return ServiceUtil.returnSuccess();
+    }
+}
\ No newline at end of file

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleServices.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java?rev=1750557&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java (added)
+++ ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java Tue Jun 28 18:50:04 2016
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.ofbiz.example;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+
+import org.ofbiz.base.util.Debug;
+
+@ServerEndpoint("/ws/pushNotifications")
+public class ExampleWebSockets {
+
+    public static final String module = ExampleWebSockets.class.getName();
+    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());
+    
+
+    @OnMessage
+    public void onMessage(Session session, String msg, boolean last) {
+        try {
+            if (session.isOpen()) {
+                synchronized (clients) {
+                    for(Session client : clients){
+                        if (!client.equals(session)){
+                            client.getBasicRemote().sendText(msg);
+                        }
+                    }
+                }
+            }
+        } catch (IOException e) {
+            try {
+                session.close();
+            } catch (IOException ioe) {
+                Debug.logError(ioe.getMessage(), module);
+            }
+        }
+    }
+
+    @OnOpen
+    public void onOpen (Session session) {
+        // Add session to the connected sessions clients set
+        clients.add(session);
+    }
+
+    @OnClose
+    public void onClose (Session session) {
+        // Remove session from the connected sessions clients set
+        clients.remove(session);
+    }
+
+    public static Set<Session> getClients () {
+        return clients;
+    }
+}
+

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/specialpurpose/example/src/org/ofbiz/example/ExampleWebSockets.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/specialpurpose/example/webapp/example/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/webapp/example/WEB-INF/web.xml?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/webapp/example/WEB-INF/web.xml (original)
+++ ofbiz/trunk/specialpurpose/example/webapp/example/WEB-INF/web.xml Tue Jun 28 18:50:04 2016
@@ -49,7 +49,7 @@ under the License.
         <init-param><param-name>disableContextSecurity</param-name><param-value>N</param-value></init-param>
         <init-param>
             <param-name>allowedPaths</param-name>
-            <param-value>/error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images:/includes/maincss.css</param-value>
+            <param-value>/error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images:/includes/maincss.css:/js:/ws</param-value>
         </init-param>
         <init-param><param-name>errorCode</param-name><param-value>403</param-value></init-param>
         <init-param><param-name>redirectPath</param-name><param-value>/control/main</param-value></init-param>

Added: ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js?rev=1750557&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js (added)
+++ ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js Tue Jun 28 18:50:04 2016
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+var webSocket;
+
+// Create a new instance of the websocket
+webSocket = new WebSocket('wss://' + window.location.host + '/example/ws/pushNotifications');
+
+webSocket.onopen = function(event){
+    // Do any operation on open
+};
+
+webSocket.onmessage = function(event) {
+
+    // Remove already present notification
+    jQuery('.pushNotification').remove();
+
+    // Create notification on the fly, this notification markup can be added in Messages.ftl and its css can be theme based.
+    jQuery("body")
+        .append(jQuery('<div/>')
+        .addClass('pushNotification')
+        .css({'position': 'fixed', 'top': '5%', 'right': '2%', 'background': 'lightgrey', 'border-radius': '10px', 'z-index': '9999'}));
+
+    jQuery('.pushNotification')
+        .append(jQuery('<a href="javascript:void(0);" class="closeNotification"/>')
+        .css({'color': 'black', 'font-size': '15px', 'position': 'fixed', 'right': '2%'}).append('close'));
+
+    jQuery('.pushNotification')
+        .append(jQuery('<p/>')
+        .addClass('msg')
+        .css({'font-size': '15px', 'padding': '30px 20px 30px 20px'}));
+
+    jQuery('.pushNotification').find('.msg').append(event.data);
+
+    // show notification
+    jQuery('.pushNotification').fadeIn();
+
+    // Remove notification after 5 seconds
+    setTimeout(function() {
+        jQuery('.pushNotification').remove();
+    }, 5000 );
+
+    // Added observer for close link.
+    jQuery('.closeNotification').click(function() {
+        jQuery(this).parent('.pushNotification').remove();
+    });
+};
+
+webSocket.onerror = function(event){
+    // Do any operation on error
+};

Propchange: ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/specialpurpose/example/webapp/example/js/ExamplePushNotifications.js
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: ofbiz/trunk/specialpurpose/example/widget/example/CommonScreens.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/example/widget/example/CommonScreens.xml?rev=1750557&r1=1750556&r2=1750557&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/example/widget/example/CommonScreens.xml (original)
+++ ofbiz/trunk/specialpurpose/example/widget/example/CommonScreens.xml Tue Jun 28 18:50:04 2016
@@ -45,6 +45,14 @@ under the License.
                 <set field="applicationTitle" value="${uiLabelMap.ExampleApplication}" global="true"/>
             </actions>
             <widgets>
+                <section>
+                    <condition>
+                        <if-has-permission permission="EXAMPLE" action="_VIEW"/>
+                    </condition>
+                    <actions>
+                        <set field="layoutSettings.javaScripts[]" value="/example/js/ExamplePushNotifications.js" global="true"/>
+                    </actions>
+                </section>
                 <include-screen name="GlobalDecorator" location="component://common/widget/CommonScreens.xml"/>
             </widgets>
         </section>