main website home
  • About this blog

    This blog features updates, opinions, and technical notes from Caucho engineers about Caucho products, the enterprise Java industry, and PHP. Caucho Technology is the creator of the Resin Application Server and the Quercus PHP in Java engine. A leader in Java performance since 1998, Caucho is a Sun JavaEE licensee with over 9000 customers worldwide.
  • Tags

    ajaxworld bam candi cdi cloud cluster comet configuration deploy devoxx eclipse ejb embedded flash flex google app engine hessian hmtp ioc java ee 6 javaone javazone jms messaging newsletter nyjug osgi php pomegranate quercus resin resin 4.0 REST servlet sfjug silicon valley code camp spring testing training tssjs watchdog webbeans web profile websockets wordpress
  • Meta

    • Register
    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.org
« Quercus/GAE at Google I/O x2, with a cool new demo!
JavaOne Wrap up »

Quercus on Google App Engine

quercusplusequalsheart-large

Ever since Google App Engine (GAE) supported Java, it has opened a slew of other languages that GAE indirectly and unofficially supports. PHP is one of them through Quercus, our 100% Java clean-room implementation of the PHP language.

PHP is unique among the other languages in that there are plenty of high-quality, killer applications (i.e. Wordpress, Mediawiki, and Drupal) that are free and readily available for it. Furthermore, there has been incessant calls for Google to support PHP from the very beginnings of GAE.

Unfortunately, GAE doesn’t support MySQL, or any other relational database for that matter. We’re limited to Google Datastore, which is pretty much a big hash table. So running existing PHP applications unmodified on GAE is currently out of the question because they are so dependent on the LAMP architecture.

But how hard is it to modify an existing PHP application to run on GAE? I set to gain insight on this interesting question by getting Wordpress running on GAE. Since Wordpress already runs on Resin with Quercus, all I needed to do was convert the MySQL queries to instead use the App Engine’s subset of JPA. In the end, it took about a week of uneventful work to get enough of Wordpress running so we could demo it at Google I/O.

quercus-gae-stack

Converting Wordpress to use JPA

The first step I undertook was to dump the database into JPA. To do so, I created a JPA entity class for each database table. The relationship from a database table to a JPA class is fairly straightforward. The table name maps to the fully qualified name of the class. Each field of the class represents a column in the table, with the field type following the column datatype as closely as possible. For example, the the wp_users table would map to something like the following JPA class:

package com.caucho.gae.wordpress271;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/*
CREATE TABLE `wp_users` (
`ID` bigint(20) unsigned NOT NULL auto_increment,
`user_login` varchar(60) NOT NULL default ”,
`user_pass` varchar(64) NOT NULL default ”,
`user_nicename` varchar(50) NOT NULL default ”,
`user_email` varchar(100) NOT NULL default ”,
`user_url` varchar(100) NOT NULL default ”,
`user_registered` datetime NOT NULL default ‘0000-00-00 00:00:00′,
`user_activation_key` varchar(60) NOT NULL default ”,
`user_status` int(11) NOT NULL default ‘0′,
`display_name` varchar(250) NOT NULL default ”,
PRIMARY KEY (`ID`),
KEY `user_login_key` (`user_login`),
KEY `user_nicename` (`user_nicename`)
);
*/

@Entity
public class User
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long _ID;
private String _userLogin;
private String _userPass;
private String _userNicename;
private String _userEmail;
private String _userUrl;
private String _userRegistered;
private String _userActivationKey;
private Long _userStatus;
private String _displayName;
}

The varchar and int types map to Java String and Long respectively. I could have used Java Date for datetime but didn’t in the end because Wordpress does all the date/time processing on its end on strings anyway. For simplicity, I omitted the Java getters and setters.

I then created a script to create and persist each table row in JPA.

The next step and final step is to convert MySQL queries to JPA queries. This is the most time-consuming step because Wordpress didn’t try to abstract the database layer from the core code. In other words, large chunks of the code are practically doing direct MySQL queries. My job was made somewhat easier by the fact that JPA queries use nearly the same syntax as SQL queries. Take the following code that retrieves the comments for a particular post:

function get_comments($post_id)
{
//SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = ‘1′ ORDER BY comment_date
$query = $this->pm->createQuery(”SELECT FROM ” . GAE_COMMENT_CLASS . ‘ WHERE _commentPostID = :id AND _commentApproved = “1″ ORDER BY _commentDate’);
$query->setParameter(”id”, $post_id);

$results = $query->getResultList();
$array = array();

foreach ($results as $comment) {
$obj = new stdClass();

$obj->comment_ID = $comment->getCommentID();
$obj->comment_post_ID = $comment->getCommentPostID();
$obj->comment_author = $comment->getCommentAuthor();
$obj->comment_author_email = $comment->getCommentAuthorEmail();
$obj->comment_author_url = $comment->getCommentAuthorUrl();
$obj->comment_author_IP = $comment->getCommentAuthorIP();
$obj->comment_date = $comment->getCommentDate();
$obj->comment_date_gmt = $comment->getCommentDateGmt();
$obj->comment_content = $comment->getCommentContent();
$obj->comment_karma = $comment->getCommentKarma();
$obj->comment_approved = $comment->getCommentApproved();
$obj->comment_agent = $comment->getCommentAgent();
$obj->comment_type = $comment->getCommentType();
$obj->comment_parent = $comment->getCommentParent();
$obj->user_id = $comment->getUserId();

$array[] = $obj;
}

return $array;
}

As you can see, it was a one-to-one conversion for this particular query. The most crucial part was to make sure I was returning the correct type that Wordpress is expecting to get back. In this case, I needed to return an array of objects.

Wordpress does sparingly use more complex query features like joins, which of the course GAE doesn’t support (yet). However, it was fairly easy for me to replicate the behavior of joins on the application side with nested loops of two or more JPA queries. Joins are evil according to Google so I do not want to bore you with the details.

After rewriting about fifty queries, I had Wordpress running satisfactory enough to demo it at Google I/O. I can edit, create, and moderate comments and posts (though I can’t guarantee any capability beyond that :). The demo is running on the App Engine at http://wordpress-on-quercus.appspot.com/wordpress-2.7.1/. The source for the war is available here.

All in all, it was a fun experience learning the ins and outs of GAE. I wouldn’t say it was feasible to adapt an existing application to Google Datastore via JPA, but as a demo it served its purpose of showcasing quercus’ seamless integration of PHP and Java.

Looking forward, we may make it brain-dead to run existing PHP applications unmodified on GAE. We already have a file-based relational database that we use for our cache and logging. We could route MySQL queries to that JNDI database instead. Since GAE doesn’t allow file writes, we’ll just then store the file-based database in Google Datastore as one big blob of data. This will allow anyone to run unmodified LAMP applications on GAE with Quercus. Now that will be very cool!

Tags: google app engine, google datastore, jpa, mysql, php, quercus, wordpress

This entry was posted on Sunday, May 31st, 2009 at 2:54 am and is filed under Engineering. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

25 Responses to “Quercus on Google App Engine”

  1. Jerzy Says:
    May 31st, 2009 at 8:31 am

    It’s very interesting! But the link for the source is broken. Could you publish the source?

  2. Emil Says:
    May 31st, 2009 at 12:13 pm

    I fixed the link - please give it another try.

    Thanks,
    Emil

  3. Herbert Says:
    May 31st, 2009 at 12:26 pm

    wow, nice demo !

    about using the datastore for file storage, it would be nice if this is implemented in Quercus as a stream, so that something like below will be possible.

    $data = file_get_contents(’datastore://some-thing-here’);
    file_put_contents(’datastore://some-thing-here’, $data);

    however, using ‘Google Datastore as one big blob of data’ for a file database (like sqLite does) does that not mean that it must retrieve & store the complete blob for every update?

    btw: I have updated my SQL to JDO wrapper, see http://blog.herbert.groot.jebbink.nl/2009/05/rom-relational-object-mapping.html for details.

  4. nam Says:
    May 31st, 2009 at 1:53 pm

    Yes, it would be possible to store files into the datastore using the standard php function calls.

    When I said to store everything as one big blob of data, I was simplifying things. The Datastore limits entities to 1MB I think, so we would need to split the data into blocks of data.

  5. Herbert Says:
    May 31st, 2009 at 3:26 pm

    Ok, sorry for a blog you must simplify, it is not a technical design :-)

    Lets dream: A VFS above the datastore and every cluster of it is an entry in the datastore. It uses memcache for caching. This VFS is mounted as / for PHP scripts. ( ./ and deeper is of course stil the war ) PHP scripts that use /tmp for example are then stil working. Oh, and also make it available as web-dav in Resin :-)

  6. abcphp.com Says:
    May 31st, 2009 at 11:44 pm

    Quercus on Google App Engine…

    Ever since Google App Engine (GAE) supported Java, it has opened a slew of other languages that GAE indirectly and unofficially supports. PHP is one of them through Quercus, our 100% Java clean-room implementation of the PHP language….

  7. WordPress on Google App Engine » gpoul’s Out Of Memory Blog Says:
    July 19th, 2009 at 7:47 am

    [...] run some PHP on GAE, what’s the first thing that comes to mind? Right… Try to run WordPress on GAE, of course [...]

  8. mikewen Says:
    July 19th, 2009 at 9:36 pm

    Can I install it on Resin Open Source ?

    I tried install it on Google App Engine (Resin 4 Open Source)

    It gave me this error:
    java.lang.NoClassDefFoundError: javax/inject/manager/Bean

    Here is the log:
    com.caucho.quercus.servlet.GoogleQuercusServlet service: java.lang.NoClassDefFoundError: javax/inject/manager/Bean
    java.lang.NoClassDefFoundError: javax/inject/manager/Bean
    at com.caucho.amber.manager.AmberPersistenceProvider.createEntityManagerFactory(AmberPersistenceProvider.java:63)
    at javax.persistence.Persistence.createFactory(Persistence.java:172)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:112)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:66)
    at com.caucho.gae.wordpress271.EMF.(EMF.java:9)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    …

  9. Emil Says:
    July 20th, 2009 at 9:59 am

    mikewen,

    It should work fine with Quercus Open Source (in fact until recently, it only worked with Quercus Open Source). At this time it’s not possible to run Resin in GAE because they force the use of Jetty. Based on your stack trace, it looks like you’re trying to use our JPA implementation, which is also not supported for GAE. You’ll need to configure the GAE JPA implementation. Finally make sure that you include all the .jars included with Resin.

    We’ll have more in depth instructions soon for Quercus on GAE.

    Thanks for trying it out!
    Emil

  10. Giki Says:
    July 21st, 2009 at 9:12 am

    Could you please change the link for the source?just don’t use GAE space for download.
    if I downloaded it with a low speed,I couldn’t finish it at all.

  11. mikewen Says:
    July 23rd, 2009 at 7:37 am

    Emil,

    Thanks for your help.

    I was able to run very simple php_info();
    (Resin in GAE, I think should be Quercus Open Source)

    The problem looks like JPA implementation not supported in GAE.
    I will wait for your instructions.
    (I know Python/PHP well, but know very little Jave )

    Mike,

  12. WordPress Runs on Google Application Engine | RubyPDF Blog Says:
    August 10th, 2009 at 8:53 pm

    [...] the rest job is convert mysql to the Goole App Engine???s subset of JPA, for details, please visit Quercus on Google App Engine. Share and [...]

  13. How to Run WordPress on Google Application Engine « PDF Hacks Says:
    August 11th, 2009 at 8:48 pm

    [...] for details, please visit Quercus on Google App Engine. [...]

  14. DL Says:
    August 16th, 2009 at 6:21 pm

    You might want to try using jiql to automatically wrap the SQL queries.

  15. sreeprashanth Says:
    August 17th, 2009 at 5:48 am

    hi, i find this post very informative, i have downloaded the rar file from your source, could you please tell how to install the wordpress in GAE and i am new to GAE also, but i am technical person. can you help me in this matter

  16. june Says:
    August 26th, 2009 at 6:46 am

    Thanks a lot for your work.

    I just add a build.xml file to enhance classes easily. Could you give me the admin password of the worpress blog ? (http://wordpress-on-quercus.appspot.com/wordpress-on-gae-quercus.zip)
    I don’t anderstand how the datastore work and I can’t edit the admin password field …

  17. alexela Says:
    September 2nd, 2009 at 9:17 am

    It’s nice this implementation. Thank you very much for the contribution. However, I encountered this issue — GAE reported always some problems on “cpu quotas”, when I tried to “login”, or to execute “test.php”, “query.php”, etc. even run the most simple function “php_info()”. Anyone can help :-(

    To “june”, you can update the password filed to “c4ca4238a0b923820dcc509a6f75849b” (which means “1″ as password in MD5) by GAE’s data viewer. Then you can login by “admin/1″

  18. floyd Says:
    October 11th, 2009 at 3:27 am

    I have a question,which is my app engine could only support files smaller than 1MB

    but http://wordpress-on-quercus.appspot.com/wordpress-on-gae-quercus.zip

    is 9.3MB,much larger than it,could you kindly tell me how to upload files larger than 1MB?

  19. ??????GAE???Wordpress???????????????????????? « ??????@?????? Says:
    October 31st, 2009 at 4:21 am

    [...]         ???GAE?????????wordpress???????????????????????????PHP???????????????PHP???Quercus??????????????????????????????Java???PHP???????????????????????????quercus?????????Google App Engine??????????????????Quercus on Google App Engine??????Quercus???GAE?????????????????????WP??????????????????????????????????????????????????????????????????????????????wp-db.php???????????????????????????JPA??????????????????????????????????????????????????????RSS???????????????????????????????????????         ???????????????jiql – ??????????????????????????????GAE?????????Mysql?????????????????????http://code.google.com/p/jiql/???jiql?????????GAE????????????MySQL??????????????????jiql??????????????????jiql???Quercus???         ?????????????????????jiql???Quercus?????????WP???PhpMyAdmin???????????????????????????????????????PHP?????????????????????????????????????????????????????????????????????jiql??????INSERT???????????????WP??????????????????????????????????????????10???????????????         ????????????WP2.8.5????????????????????????????????????????????????Java????????????java.net.Proxy????????????http.php????????????????????????????????????Socks?????????????????????????????????????????????????????????????????????????????????????????????require??????wp-settings.php:352????????????????????????????????? [...]

  20. benjaminauffarth Says:
    January 2nd, 2010 at 12:30 pm

    First, thanks for great work!

    I am trying to run this, first locally out of the box (with only two changes relating to appengine project name). I run the project like this:

    ./[..]appengine-java-sdk-1.3.0/bin/dev_appserver.sh .

    and get the message “The server is running at http://localhost:8080/”

    At http://localhost:8080/wordpress-2.7.1/wp-admin/install.php I got this error:
    [..]wordpress/wordpress-2.7.1/wp-admin/includes/schema.php:22: Fatal Error: Call to undefined method GaeDb::has_cap()

    I commented out lines 22 to 28 and now I reached a wordpress install screen and entered an email and blog name, but then I get more errors. I can get rid off one by changing a line in upgrade.php::1549 to $result=1;

    However I think this error here is end of the line for me without major tinkering:

    [..] wordpress-2.7.1/wp-admin/includes/upgrade.php:1140: Fatal Error: Call to undefined method GaeDb::get_col()

    Is there a way I can get this to run?

  21. a199145 Says:
    March 6th, 2010 at 12:34 pm

    how do i config the wp-config.php file?

    DB_NAME
    DB_USER
    DB_PASSWORD
    DB_HOST

    what shall i fill in with?

    and can u release a latest modified wp?

  22. HM2K.com » Getting started with Quercus in Google App Engine Says:
    April 15th, 2010 at 6:28 am

    [...] Converting Wordpress for Quercus on Google App Engine [...]

  23. flynn Says:
    July 30th, 2010 at 7:19 pm

    hello you guys, I set up a wordpress2.7.1 on google app engine, but when I log in, and click the admin site, I always get something like:

    /base/data/home/apps/iamawordpressapp/7.343726665455507144/wordpress-2.7.1/wp-includes/user.php:364: Fatal Error: Call to undefined method GaeDb::prepare()

    how to fix this?

  24. marciosfalsin Says:
    February 16th, 2011 at 6:00 pm

    Hi there! I’m converting some files that still not converted or presents some error, from this wordpress version, as I complete it, I’ll put the link here!

  25. Caucho Technology » Blog Archive » Quercus on Google App Engine - 2.0 Says:
    December 6th, 2012 at 6:54 am

    [...] 3.5 years ago to this day since I last wrote about running Quercus on Google App Engine (GAE). The article detailed a crazy experiment to get a PHP application, Wordpress, running on GAE. I still remember [...]

Leave a Reply

You must be logged in to post a comment.


Caucho Technology is proudly powered by WordPress and Quercus®
Entries (RSS) and Comments (RSS).

  • HOME |
  • CONTACT US |
  • DOCUMENTATION |
  • BLOG |
  • WIKI 4 |
  • WIKI 3 |
  • Resin: Java Application Server
Copyright (c) 1998-2012 Caucho Technology, Inc. All rights reserved.
caucho® , resin® and quercus® are registered trademarks of Caucho Technology, Inc.
resin® is a cloud optimized, java® application server that supports the java ee webprofile ®