Ok, so my further experiments in how to make Jython work on GAE/J have led me to attempting the Google Web Toolkit example, and see if I can drive the server code using Jython, and I have success. So, with GWT, I can build a UI in Java (that compiles into JavaScript), and then I can write the server-side components in Jython (thanks to Josh's little Object Factory trick he helped me with earlier), so I can build the server-end with Jython (the only limitation is dealing with the DataStore, using JDO, I still need to build a couple Java classes to handle that gracefully, but even that works like a charm).

JDO:
from import javax.jdo import JDOHelper

PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional")

pm = PMF.getPersistenceManager()

try:
    pm.makePersistent(Stock(user, symbol)) # Any class properly annotated for JDO here
finally:
    pm.close()
This *will* fail. The reason is because the getPersistenceManager() method doesn't return a PersistenceManager object, but something else from the DataNucleus system. Building a PMF class (as outlined in the GAE/J example for "guestbook"), and adding a method to return a PersistenceManager object directly in Java like:
package com.google.gwt.sample.stockwatcher.server;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {
    private static final PersistenceManagerFactory pmfInstance =
        JDOHelper.getPersistenceManagerFactory("transactions-optional");

    private PMF() {}

    public static PersistenceManager getPM() {
        return (PersistenceManager) pmfInstance.getPersistenceManager();
    }
}
And then loading that into the above Python code changes it to:
from import javax.jdo import JDOHelper
from com.google.gwt.sample.stockwatcher.server import PMF

pm = PMF.getPM()

try:
    pm.makePersistent(Stock(user, symbol)) # Any class properly annotated for JDO here
finally:
    pm.close()
This will work correctly then.

GWT:
from com.google.gwt.user.server.rpc import RemoteServiceServlet

from com.google.gwt.sample.stockwatcher.client import StockPrice, StockPriceService, DelistedException

import sys

sys.path.insert(0, 'WEB-INF/python-lib/Lib.zip')

import random

MAX_PRICE = 100.0       # $100.00
MAX_PRICE_CHANGE = 0.02 # +/- 2%

class StockPriceServiceImpl(RemoteServiceServlet, StockPriceService):
   
    def getPrices(self, symbols):
        prices = []
        for i in range(len(symbols)):
            if symbols[i] == "ERR":
                raise DelistedException("ERR")
           
            price = random.random() * MAX_PRICE
            change = price * MAX_PRICE_CHANGE * (random.random() * 2.0 - 1.0)
           
            prices.append(StockPrice(symbols[i], price, change))
           
        return prices
package com.google.gwt.sample.stockwatcher.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import org.plyjy.factory.JythonObjectFactory;

import com.google.gwt.sample.stockwatcher.client.DelistedException;
import com.google.gwt.sample.stockwatcher.client.StockPrice;
import com.google.gwt.sample.stockwatcher.client.StockPriceService;

public class StockPriceServiceFacade extends RemoteServiceServlet implements StockPriceService {

    private JythonObjectFactory factory = null;

    String pyServletName = null;

    @Override
    public StockPrice[] getPrices(String[] symbols) throws DelistedException {
        factory = factory.getInstance();
        pyServletName = getInitParameter("PyServletName");
        StockPriceService jythonServlet = (StockPriceService) factory.createObject(StockPriceService.class, pyServletName);
        return jythonServlet.getPrices(symbols);
    }

}

So, now that I have done this... my next step is to try and build something from scratch with all of this. I'm really enjoying the ability to use Jython on the Google Apps Engine...

--
"I'm not responcabel fer my computer's spleling errnors" - Xlorep DarkHelm
Website: http://darkhelm.org
Sent from Santa Maria, California, United States