Friday, August 28, 2009

Dynamic-height in Shindig

Gadget specification provides a feature called dynamic-height to dynamically adjust height of a gadget.
If gadget server and gadget container are in the same domain, this can be done using javascript.
However, if gadget server and gadget container are in different domains, this can not be achieved by directly using Javascript and DOM because of same-origin policy imposed by modern browsers.
This email http://markmail.org/message/53r5dwhr56lby733#query:dynamic%20height%20shindig+page:1+mid:53r5dwhr56lby733+state:results includes some information about how to make it work.
I am going to give more details here.

Gadget container

  1. Download
        http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/cookies.js
        http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/gadgets.js
        http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/util.js
        http://your_shindig_deploy/gadgets/js/rpc.js?c=1&debug=1 (//this file actually includes rpc framework and all possible communication mechanism, e.g. ifpc, wpm...)
    And put them into your gadget container server.
  2. Include following code in your container web page to make them point to those javascript files you downloaded in step 1).
    <script type="text/javascript" src="rpc.js"></script>
    <script type="text/javascript" src="cookies.js"></script>
    <script type="text/javascript" src="util.js"></script>
    <script type="text/javascript" src="gadgets.js"></script>
  3. Download
        rpc_relay.html : http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.html
    or
        rpc_relay_uncompressed.html: http://svn.apache.org/repos/asf/incubator/shindig/trunk/javascript/container/rpc_relay.uncompressed.html

Gadget server/renderer

  1. Check out Shindig source code. See http://incubator.apache.org/shindig/source-repository.html
  2. Change source code of file ifpc.transport.js
    Original:
    // The RPC mechanism supports two formats for IFPC (legacy and current). var src = null; if (rpc.l) {
    New
    // The RPC mechanism supports two formats for IFPC (legacy and current).
    var src = null;
    if (false) {
    This disables use of legacy data format which is buggy.
  3. Change configuration in file config/container.js
        Original: "parentRelayUrl" : "/gadgets/files/container/rpc_relay.html"
        New:       "parentRelayUrl" : "rpc_relay file address on your gadget container" //it is download in this step
    Also you may want to use ifpc instead of browser-specific communication mechanisms.
        Original: "useLegacyProtocol" : false    //gadget tries browser-specific communication mechanisms first. If they fail, fall back to ifpc.
        New:      "useLegacyProtocol" : true           //use ifpc directly.
    Note: the current wire format will be used instead of legacy format because we have disabled legacy format.
    This option is not used in the way described by comment in the source code. The shindig developers want users to use this option to control whether legacy format is used. I use it to configure whether ifpc is used. If ifpc is used, only current wire format is utilized.
    This can also be set after you deploy shindig. The configuration file is located at WEB-INF/classes/containers/default/.
  4. Rebuild shindig.
  5. Copy generated .war file in directory server/target to your servlet container.

Resources

Detailed discussion: http://docs.google.com/View?id=dmxthpg_125ckh55fff
Cross-Domain Communication with IFrames: http://softwareas.com/cross-domain-communication-with-iframes

Friday, August 21, 2009

Google GData API usage

Recently, I am using Google GData APIs to access Google Picasa and Google Calendar Services.
There is a Java library which is hosted at http://code.google.com/p/gdata-java-client/. Currently, the code is maintained using ant. We use maven2 to build our project, so we manually uploaded those jars to our maven repository and added necessary pom files. Dependencies of gdata java library are described at http://code.google.com/p/gdata-java-client/wiki/Dependencies.
Google Picasa doc: http://code.google.com/apis/picasaweb/docs/2.0/developers_guide.html
Google Calendar doc: http://code.google.com/apis/calendar/docs/2.0/developers_guide.html

During using of Google Calendar APIs, one thing I want to do is publish a new event to a specific non-primary calendar. According to http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle, POST requests should be sent to http://www.google.com/calendar/feeds/default/private/full. However that results in putting new event to primary calendar. The document does not tell us how to put a new event to non-primary calendar.

Solution (How to publish a new event to a non-primary calendar)

Steps:
  1. Get a list of all calendars owned by the user
    Send GET request to http://www.google.com/calendar/feeds/default/owncalendars/full
  2. In the response feed, each calendar has an entry.
    Each entry should has a link element like this:
        <link rel="alternate"
                 type="application/atom+xml"
                 href="http://www.google.com/calendar/feeds/pnk4d66rpmiho1pl0m4t6dnki0%40group.calendar.google.com/private/full"/>
    Value of attribute href is the URL to which the POST request should be sent to create a new event in the corresponding calendar.
  3. Send POST request to the URL specified by attribute "href" found in step 2)
    Example of POST data is shown http://code.google.com/apis/calendar/docs/2.0/developers_guide_protocol.html#CreatingSingle


Monday, August 10, 2009

MySQL Connection Timeout Error in Hibernate

Problem

I am using Hibernate and MySQL in myour project. After our application is started, it just works well. However, if the application is not used for some time (like one day), it throws connection exception when it is used again. Trace of the exception:
com.mysql.jdbc.CommunicationsException: 
The last packet successfully received from the server was seconds ago.
The last packet sent successfully to the server was 407270 seconds ago, which  is longer than the server configured value of 'wait_timeout'. 
You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

I googled this problem, and it seems that many other persons also suffer this problem. I found some really nice blog posts about how to solve this problem.

According to the error message, I set the option autoReconnect (http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html) to true. But it still does not work. I searched in google and it shows this option works in some platforms while it doesn't work in other platforms.

Solution

Basically, the solution is 1) use a connection manager 2) tweak parameters of the connection manager.

C3P0 is a free JDBC connection manager.
Some C3p0 configuration parameters are mapped to Hibernate config. Those mapped configuration parameters are listed at http://www.mchange.com/projects/c3p0/index.html#hibernate-specific.

"Please note that configuration parameters that ARE mapped into hibernate's config file MUST be set within hibernate's configuration, or else they will be overridden by hibernate-specified defaults.
[The hibernate-mapped c3p0 parameters are minPoolSize, maxPoolSize, maxIdleTime, maxStatements, acquireIncrement, testConnectionOnCheckout, and idleConnectionTestPeriod. These map to the fllowing hibernate parameters: hibernate.c3p0.min_size, hibernate.c3p0.max_size, hibernate.c3p0.timeout, hibernate.c3p0.max_statements, hibernate.c3p0.acquire_increment, hibernate.c3p0.validate, and hibernate.c3p0.idle_test_period. DataSources configured in Tomcat should always use c3p0-native parameter names. But pools constructed under the covers by Hibernate must be configured in hibernate's config file with hibernate-defined parameter names where applicable.] "

For those C3p0 parameters that are NOT mapped, they should be specified in file WEB-INF/classes/c3p0.properties.
Note: C3P0 configuration parameter <c3p0.testConnectionsOnCheckout> is mapped to <hibernate.c3p0.validate> only in hibernate 2.x!
Also the configuration parameter c3p0.testConnectionsOnCheckout is really expensive. Users can use c3p0.maxIdleTime (it is mapped to hibernate.c3p0.timeout in hibernate) instead.

My hibernate.cfg.xml includes following configuration:
        <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
        <property name="c3p0.min_size">5</property>
        <property name="c3p0.max_size">30</property>
        <property name="c3p0.timeout">600</property>
        <property name="c3p0.max_statements">0</property>
        <property name="c3p0.acquire_increment">5</property>
        <property name="c3p0.idle_test_period">60</property>

The idle test operation can be optimized by specifying option preferrredTestQuery.
I am using MySQL as underlying RDB and putting c3p0.preferredTestQuery = SELECT 1 into c3p0.properties works fine (this is stolen from post comment http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/#comment-3156).

Resources

A really good article about how to reconnect from Hibernate to MySQL: http://www.databasesandlife.com/automatic-reconnect-from-hibernate-to-mysql/
C3P0 (Connection manager): http://www.mchange.com/projects/c3p0/index.html
How to configure C3P0 in Hibernate: https://www.hibernate.org/214.html
A forum thread about C3P0 configuration in Hibernate: https://forum.hibernate.org/viewtopic.php?t=934779&highlight=c3p0