Wednesday, December 31, 2008

Deploying Shindig in a non root context

Shindig is configured, by default, to be accessed in ROOT context. While this is ok for development purposes, it is not desirable in a production setting where main applications may already be running in ROOT context OR in cases where a web server acts as a HTTP Reverse Proxy for an Appserver.

This post describes the steps I followed to make Shindig gadget and opensocial containers work on my Tomcat Server in a non-Root Context. Thanks a ton to Kevin Brown for providing valuable pointers in this email chain.

The following steps would enable deployment of Shindig in a non Root context on Tomcat and other AppServers.

1) Build shindig using steps provided at http://incubator.apache.org/shindig/#tab-building

2) Copy shindig/java/server/target/shindig-server-1.1-SNAPSHOT.war to a temporary folder (say c:\temp)

3) cd c:\temp

4) unzip shindig-server-1.1-SNAPSHOT.war to c:\temp\shindig folder

5) cd shindig/WEB-INF/classes/containers/default

6) Open container.js in a text editor. Since the default setting assumes shindig to be in the root context, it is necessary to modify all URLs for opensocial calls to work correctly. After updating all URLs, save changes and close container.js.

(There are some properties in shindig still that are pending migration to container.js, hence step#7 to 10. Thanks Carmen and Gerald for this suggestion)

7) Extract shindig.properties from shindig/WEB-INF/lib/shindig-common-1.1-SNAPSHOT.jar to shindig/WEB-INF/classes folder

8) Remove shindig.properties from shindig/WEB-INF/lib/shindig-common-1.1-SNAPSHOT.jar

9) cd shindig/WEB-INF/classes

10) Open shindig.properties in a text editor. Since the default setting assumes shindig to be in the root context, it is necessary to modify all URLs for gadget/concat calls to work correctly.

11) Fix Shindig's sample opensocial container "samplecontainer"
(a) cd c:/temp/shindig/gadgets/files/samplecontainer
(b) Open samplecontainer.js in a text editor
(c) Append Shindig's context name in the URL assigned to the variable "socialDataPath" (line# 44)
(d) Append Shindig's context name in the URI passed to sendRequestToServer() within requestGadgetMetaData function (line# 192)
(e) save & close samplecontainer.js
(f) cd examples
(g) Open all gadget xmls and, update URL of images (for ex:- bubble.gif, nophoto.if etc.)
(h) Also, make the changes mentioned in steps b-g for samplecontainer provided under c:/temp/shindig/WEB-INF/classes/gadgets/files/samplecontainer

12) Zip the contents of shindig folder and rename the zip file as shindig.war or any other name based on your preference.

13) This war file would now work on Tomcat or any other app server in a non-root context

Friday, August 22, 2008

Google Gadget XSD doesn't pass XSD validation

If you are having trouble getting your development tools to work smoothly with gadget XSD to do tasks such as validating & parsing gadget xmls, then look no further. The problem lies in gadget XSD itself. The latest and greatest version 0.8 of the gadget is not a valid XSD.

Proof: Run it through W3C XSD validator and you will find close to 12 errors.

Here is the fixed XSD. Let me know if this works for you.

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Module">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ModulePrefs" minOccurs="0">
          <xs:complexType>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
              <xs:element name="Require" type="GadgetFeatureType"/>
              <xs:element name="Optional" type="GadgetFeatureType"/>
              <xs:element name="Preload">
                <xs:complexType>
                  <xs:attribute name="href" type="xs:string" use="required"/>
                  <xs:attribute name="authz" default="none">
                     <xs:simpleType>
                      <xs:restriction base="xs:string">
                        <xs:enumeration value="none"/>
                        <xs:enumeration value="signed"/>
                        <xs:enumeration value="oauth"/>
                      </xs:restriction>
                    </xs:simpleType>
                  </xs:attribute>
                  <xs:attribute name="sign_owner" type="xs:boolean" default="true"/>
                  <xs:attribute name="sign_viewer" type="xs:boolean" default="true"/>
                  <xs:attribute name="views" type="xs:string" use="optional"/>
                </xs:complexType>
              </xs:element>
              <xs:element name="Icon">
                <xs:complexType>
                  <xs:simpleContent>
                    <xs:extension base="xs:string">
                      <xs:attribute name="mode">
                        <xs:simpleType>
                          <xs:restriction base="xs:string">
                            <xs:enumeration value="base64"/>
                          </xs:restriction>
                        </xs:simpleType>
                      </xs:attribute>
                      <xs:attribute name="type" type="xs:string"/>
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
              <xs:element name="Locale">
                <xs:complexType>
          <xs:sequence>
            <xs:element name="msg" minOccurs="0" maxOccurs="unbounded">
            <xs:complexType>
              <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="name" type="xs:string" use="required"/>
                <xs:attribute name="desc" type="xs:string" use="optional"/>
              </xs:extension>
              </xs:simpleContent>
            </xs:complexType>
            </xs:element>
          </xs:sequence>
                  <xs:attribute name="lang" type="xs:string" use="optional"/>
                  <xs:attribute name="country" type="xs:string" use="optional"/>
                  <xs:attribute name="messages" type="xs:string" use="optional"/>
                  <xs:attribute name="language_direction">
                    <xs:simpleType>
                      <xs:restriction base="xs:string">
                        <xs:enumeration value="ltr"/>
                        <xs:enumeration value="rtl"/>
                      </xs:restriction>
                    </xs:simpleType>
                  </xs:attribute>
                </xs:complexType>
              </xs:element>
              <xs:element name="Link">
                <xs:complexType>
                  <xs:attribute name="href" type="xs:string" use="required"/>
                  <xs:attribute name="rel" use="required">
                    <xs:simpleType>
                      <xs:restriction base="xs:string">
                        <xs:enumeration value="gadgets.help"/>
                        <xs:enumeration value="gadgets.support"/>
                        <xs:enumeration value="icon"/>
                      </xs:restriction>
                    </xs:simpleType>
                  </xs:attribute>
                </xs:complexType>
              </xs:element>
              <xs:element name="OAuth" minOccurs="0" maxOccurs="1">
                <xs:complexType>
          <xs:sequence>
            <xs:element name="Service" maxOccurs="unbounded">
            <xs:complexType>
            <xs:sequence>
              <xs:element name="Request" type="OAuthResourceType" minOccurs="0"/>
              <xs:element name="Access" type="OAuthResourceType" minOccurs="0"/>
              <xs:element name="Authorization" minOccurs="0">
              <xs:complexType>
                <xs:attribute name="url" type="xs:string" use="required"/>

              </xs:complexType>
              </xs:element>
              </xs:sequence>
            </xs:complexType>
            </xs:element>
            </xs:sequence>
                  <xs:attribute name="name" type="xs:string" use="optional"/>
                </xs:complexType>
              </xs:element>
            </xs:choice>
            <xs:attribute name="title" type="xs:string" use="optional"/>
            <xs:attribute name="title_url" type="xs:string" use="optional"/>
            <xs:attribute name="description" type="xs:string" use="optional"/>
            <xs:attribute name="author" type="xs:string" use="optional"/>
            <xs:attribute name="author_email" type="xs:string" use="optional"/>
            <xs:attribute name="screenshot" type="xs:string" use="optional"/>
            <xs:attribute name="thumbnail" type="xs:string" use="optional"/>
            <xs:attribute name="directory_title" type="xs:string" use="optional"/>
            <xs:attribute name="author_affiliation" type="xs:string" use="optional"/>
            <xs:attribute name="author_location" type="xs:string" use="optional"/>
            <xs:attribute name="author_photo" type="xs:string" use="optional"/>
            <xs:attribute name="author_aboutme" type="xs:string" use="optional"/>
            <xs:attribute name="author_quote" type="xs:string" use="optional"/>
            <xs:attribute name="author_link" type="xs:string" use="optional"/>
            <xs:attribute name="show_stats" type="xs:boolean" use="optional"/>
            <xs:attribute name="show_in_directory" type="xs:boolean" use="optional"/>
            <xs:attribute name="string" type="xs:string" use="optional"/>
            <xs:attribute name="width" type="xs:int" use="optional"/>
            <xs:attribute name="height" type="xs:int" use="optional"/>
            <xs:attribute name="category" type="xs:string" use="optional"/>
            <xs:attribute name="category2" type="xs:string" use="optional"/>
            <xs:attribute name="singleton" type="xs:boolean" use="optional"/>
            <xs:attribute name="render_inline" type="xs:string" use="optional"/>
            <xs:attribute name="scaling" type="xs:boolean" use="optional"/>
            <xs:attribute name="scrolling" type="xs:boolean" use="optional"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="UserPref" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="EnumValue" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:attribute name="value" type="xs:string" use="required"/>
                  <xs:attribute name="display_value" type="xs:string" use="optional"/>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="name" type="xs:string" use="required"/>
            <xs:attribute name="display_name" type="xs:string" use="optional"/>
            <xs:attribute name="default_value" type="xs:string" use="optional"/>
            <xs:attribute name="required" type="xs:string" use="optional"/>
            <xs:attribute name="datatype" default="string">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:enumeration value="string"/>
                  <xs:enumeration value="hidden"/>
                  <xs:enumeration value="bool"/>
                  <xs:enumeration value="enum"/>
                  <xs:enumeration value="list"/>
                  <xs:enumeration value="number"/>
                  <xs:enumeration value="location"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="urlparam" type="xs:string" use="optional"/>
            <xs:attribute name="autocomplete_url" type="xs:string" use="optional"/>
            <xs:attribute name="num_minval" type="xs:double" use="optional"/>
            <xs:attribute name="num_maxval" type="xs:double" use="optional"/>
            <xs:attribute name="str_maxlen" type="xs:int" use="optional"/>
            <xs:attribute name="restrict_to_completions" type="xs:boolean" use="optional"/>
            <xs:attribute name="prefix_match" type="xs:boolean" use="optional"/>
            <xs:attribute name="publish" type="xs:boolean" use="optional"/>
            <xs:attribute name="listen" type="xs:boolean" use="optional"/>
            <xs:attribute name="on_change" type="xs:string" use="optional"/>
            <xs:attribute name="group" type="xs:string" use="optional"/>
          </xs:complexType>
        </xs:element>
        <xs:element name="Content" minOccurs="1" maxOccurs="unbounded">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="type" use="optional" default="html">
                  <xs:simpleType>
                    <xs:restriction base="xs:string">
                      <xs:enumeration value="html"/>
                      <xs:enumeration value="url"/>
                      <xs:enumeration value="html-inline"/>
                    </xs:restriction>
                  </xs:simpleType>
                </xs:attribute>
                <xs:attribute name="href" type="xs:string" use="optional"/>
                <xs:attribute name="view" type="xs:string" use="optional"/>
                <xs:attribute name="preferred_height" type="xs:integer" use="optional"/>
                <xs:attribute name="preferred_width" type="xs:integer" use="optional"/>
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="GadgetFeatureType">
    <xs:sequence>
      <xs:element name="Param" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute name="name" type="xs:string" use="required"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="feature" type="xs:string" use="required"/>
  </xs:complexType>
  <xs:complexType name="OAuthResourceType">
    <xs:attribute name="url" type="xs:string" use="required"/>
    <xs:attribute name="method" use="optional" default="GET">
  <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="GET"/>
        <xs:enumeration value="POST"/>
      </xs:restriction>
    </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="param_location" use="optional" default="header">
  <xs:simpleType>
      <xs:restriction base="xs:string">
        <xs:enumeration value="header"/>
        <xs:enumeration value="url"/>
        <xs:enumeration value="body"/>
      </xs:restriction>
    </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
</xs:schema>

Wednesday, August 6, 2008

Enable gzip compression on Apache web server in 3 easy steps

Make the following changes in apache/conf/httpd.conf :-

1) Uncomment "LoadModule deflate_module modules/mod_deflate.so"

2) Add "SetOutputFilter DEFLATE" inside <<IfModule mime_module> section

3) Add "AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript text/css" right after SetOutputFilter... line.

Restart Apache. You should see a significant improvement in the turnaround time for your web applications. This setting works for all responses tunneled trough Apache for ex:- for java web applications deployed on a Tomcat integrated with apache web server etc.

Tuesday, June 24, 2008

Integrate php with MySQL

Open {PHP_DIR}/php.ini
1) Check if the extension directory is set correctly. is is set incorrectly in the php.ini file that ships with the installer. In that , Replace extension_dir="./" with extension_dir="./ext/"
(2) Uncomment extension=php_mysql.dll
(3) You should now be able to access your mysql database.

Integrate Apache 2.x with Php 5

Open {APACHE_DIR}/conf/httpd.conf
1) Enable mod rewrite by uncommenting or adding LoadModule rewrite_module modules/mod_rewrite.so

2) Add the following lines in the load module section
PHPIniDir "C:/Program Files/php"
LoadModule php5_module "C:/Program Files/php/php5apache2_2.dll"

3) Add php mime type
(a) Search for "IfModule mime_module" tag
(b) Add the following lines right after the "TypesConfig conf/mime.types"
AddType application/x-httpd-php .php
AddType application/x-httpd-php .php .html

(4) Allow full control to Apache's root folder that contains php files by creating or modifying (if one already exists) the <Directory> element for the root folder. Since the root folder for php is {APACHE_DIR}/htdocs folder itself on my machine, the directory entry looks like this:-

Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all


(5) Test the setup. Create a new file called info.php under {APACHE_DIR}/htdocs folder. Copy & paste the following lines into info.php
<?php
phpinfo();
?>>


(6) Access info.php from the browser . The integration with Apache is successful if you see a page that lists information about the php environment installed on your machine.

Installing php5

On Windows XP Pro:-
1) download php's installation zip file from http://www.php.net
2) Unzip the files to "C:/Program Files/php" folder
3) Add "C:/Program Files/php" to the PATH environment variable. Right click My Computers->properties->Advanced->Environment Variables. Update PATH variable under system variables section.
4) rename php.ini-dist as php.ini under "C:/Program Files/php" folder
5) Restart PC. This makes the os load all files residing in "C:/Program Files/php" folder.
6) After restart, open command line window (start->run->cmd.exe) and run php -version
7) The installation is successful if the php interpreter shows version information without any errors or exceptions

Tuesday, June 10, 2008

Integrate Apache Web Server 2.x with Tomcat 6.x on Windows XP

1) Enable Apache's HTTP proxy module by uncommenting the following lines in {APACHE_DIR}/conf/httpd.conf

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

2) Right at the end of the Load module section in httpd.conf, register URLs that should be forwarded to Tomcat like this:-
ProxyPass relative_url translated_url

For ex, Accessing a web application named 'tp' deployed on a local Tomcat server listening on port 8080 through Apache's http proxy (http://localhost/tp) would like this:-
ProxyPass /tp http://localhost:8080/tp

3) Add Apache's proxy to Tomcat's <connector> element associated with port 8080 in {TOMCAT_DIR}/conf/server.xml by adding the proxy attributes like this:-
<connector port="8080" protocol="HTTP/1.1"
connectiontimeout="20000"
redirectport="8443"
proxyName="localhost"

proxyPort="80"/>

That's all there is to it. You should now be able to access tomcat via Apache Web Server's HTTP reverse proxy.