Category: Web Apps

Great site about Google AppEngine Java Edition

Wow, at http://gaejexperiments.wordpress.com/ you will find heaps of tutorials and hints on Googles AppEngine. Thanks to Romin K. Irani, who assembled all of them and even provides them for downloads as an 227 pages strong eBook.

Use a Highlighter on this page

Object with id “” is managed by a different Object Manager

Here I go again with Tapestry. And I am getting somewhere following along this the “Tapestry for Nonbelievers” tutorial. Displaying a list of users, adding and editing them. My colleague added the first little Ajaxy bits and pieces to it and so it was about time to allow to implement the embedded classes. Displaying the embedded properties was ok by editing the BeanModel and adding the fields to it manually (explained in a mailing list). I also managed to get to the state of adding new users with the embedded fields, but than stumbled as I tried to update an existing one.

I got the abover error message: Object with id “” is managed by a different Object Manager.

After a while I figured out, that the model classes do need to be marked as detachable and then detach when retrieving them from the datastore. All three classes involved (user, contactInfo, address) are now marked as follows:

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")

And my BaseDAOImpl.java detaches objects on find and findAll (below only find example, for findAll us pm.detachCopyAll):

@Override
 public T find(long id) {
    T obj;
    try {
       getPersistenceManager();
       T obj_temp = (T) pm.getObjectById(_class, KeyFactory.createKey(_class.getSimpleName(), id));
       obj = pm.detachCopy(obj_temp);
    } finally {
       pm.close();
    }
    return obj;
 }

That was that. Another little mystery solved and something that I learned and won’t forget.

Use a Highlighter on this page

App Engine and JDO: Object Manager has been closed

So, there I am, super happy with Tapestry on Google App Engine so far I started building access to the Datastore using JDO and following the guidelines to create a PersistenceManagerFactory as singleton as the App Engine documentation suggests. Also created my DAOs and went off trying it out creating a new object to store. So far so good, but when I tried to retrieve the list of objects from the Datastore, I got this error:

An unexpected application exception has occurred.
Render queue error in SetupRender[Index:grid]: Failure reading parameter ‘source’ of component Index:grid: Object Manager has been closed

Mh, that’s weird. The code I used looked just fine to me. But then I did some googling around and figured, that it’s because the PersistenceManager is closed after the query, but the data actually hasn’t been retrieved yet. And as soon as the page gets rendered and want’s to acces the data for display, of course, nothing is there. That is some sort of lazy loading, which is supposed to keep load down and only retrieve data that actually is used. Luckily, there is a simple solution as suggested from one of the Google guys in a thread about that issue at Google Groups. It’s as simple as calling the size() method on the list before closing the Persistence Manager. Not the neatest, but a working solution. There is another approach here for use with JPA and EntityManager (works around the closing issue as well) and for users of Spring using the OpenPersistenceManagerInViewFilter. A similar issue for One-To-Many relationships is discussed at stackoverflow.

A bug report has been submitted for that already. If anyone knows of a nice way to solve that then calling size(), please leave a short note in the comments.

For the sake of completeness, here the result of that little workaround for my BaseDAO findAll method.

@Override
 public List<T> findAll() {
 try {
 initializePersistanceManager();
 String query = "select from " + _class.getName();
 List<T> objects = (List<T>) pm.newQuery(query).execute();
 objects.size(); // This is the workaround to retrieve all objects
 return objects;
 } finally {
 pm.close();
 }
 }
Use a Highlighter on this page

Local Unit Testing for Google AppEngine projects

Well, it’s pretty well explained in Googles documentation, but for me it’s quicker to have a reminder in my own blog.

Add the following jars to the Build path

  1. appengine-api-stubs.jar
  2. appengine-testing.jar
  3. junit-3.8.2.jar (or whatever current version there is right now

That enables simple testing as well as Service testing. For the latter you add a field to your Test class and setup as well as teardown methods:

public class UserServiceTest extends TestCase {

 private final LocalServiceTestHelper helper =
 new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

 //@Before
 public void setUp(){
 helper.setUp();
 }

 //@After
 public void tearDown(){
 helper.tearDown();
 }

 public void doSomeTesting(){
 }

}
Use a Highlighter on this page

Getting started with Tapestry 5.1 on Google App Engine

Looking into some other technologies for web development other than the Symfony-Framework (PHP) I ran into the Tapestry Framework (JAVA) after I had played a little bit with Wicket, and really liked its approach, but than figured out it doesn’t play nice with the Google App Engine. So since a friend mentioned the Tapestry Framework as another component oriented Framework, I went off today to have a look at it. Unfortunately there aren’t any equally good tutorials or howtos on how to get started with Tapestry on Google App Engine as for Wicket, so my goal for today was to just get started with it. And since I managed at the end, I am going over the steps here as a reminder to myself and possibly quickstart for others. Read more »

Use a Highlighter on this page

sfPropelActAsTaggableBehavior user_id enhancement

I love symfony (aka the PHP Symfony Framework) for the structure it brings to application development. Finally all the patterns known from e.g. the JAVA world are accessible (and required) in a PHP environment. I presume, this will make future web applications based on it a lot more stable, error prone and enhanceable.

Another aspect is the speed of the development once you got used to it and know the basics. But then there is always the point you stumble with your knowledge and can’t really proceed. This happened to me while implementing the faboulous sfPropelActAsTaggableBehavior plugin. It adds with a bit of configuration the ability to have tags for all your propel based objects. The documentation provided is great and functionality out of the box close to complete. Close only though.

The Requirement

I have an application I use since symfony 1.0 to get to know the latest framework updates. I gonna get it out for production use soon and wanted to add some last gimmicks. The application allows you to get nutrient informations for food and to track it in a personal diary. I thought adding tags would be very beneficial as it allows users to easily group it as required. And this could be done for foods as well as receipes (though not yet implemented), I checked out the sfPropelActAsTaggableBehaviour plugin. And it is all I needed, but the fact that I don’t want any user to remove tags that are not his own.

The Solution

I figured the best way to accomplish what I needed is to enhance the sf_tagging table in the schema with a reference to my sf_guard_user as follows:

sf_tagging:
_attributes:      { phpName: Tagging, package: plugins.sfPropelActAsTaggableBehaviorPlugin.lib.model }
id:               { phpName: ID, type: integer, required: true, primaryKey: true, autoincrement: true }
tag_id:           { type: integer, required: true, foreignTable: sf_tag, foreignReference: id, onDelete: CASCADE }
taggable_model:   varchar(30)
taggable_id:      integer
user_id:          { type: integer, default: null, required: false, foreignTable: sf_guard_user, foreignReference: id, onDelete: SETNULL }
_indexes:
tag:            [tag_id]
taggable:       [taggable_model, taggable_id]

So far so good. But than I stumbled implementing it into the plugin code. I also checked the forums and couldn’t find any help there. Sending an email to the developer was not of success either, which I can understand as answering every bloody request from noobs and intermediates would get quite time consuming. What’s left? Bloody learn the trick. So read the chapter about mixins in the symfony book (Chapter 17: Extending Symfony) and an a tutorial that explains the development of the the Paranoid Behavior.

That helped me to understand I was looking in the wrong places as the configured model classes (for Food and Receipe) were enhanced with hooks that execute the code in the sfPropelActAsTaggableBehavior.class.php.  In here it is the method public function postSave(BaseObject $object) I need to enhance. In the first foreach loop I added the following code:

// save new tags
foreach ($tags as $tagname)
{
$tag = TagPeer::retrieveOrCreateByTagName($tagname);
$tag->save();
$tagging = new Tagging();
$tagging->setTagId($tag->getId());
$tagging->setTaggableId($object->getPrimaryKey());
$tagging->setTaggableModel(get_class($object));
if(sfContext::getInstance()->getUser()->isAuthenticated())
$tagging->setUserId(sfContext::getInstance()->getUser()->getGuardUser()->getId());
else
$tagging->setUserId(null);
$tagging->save();

}

And yeah, it works flawlessly. :)

What’s left

Working on the behavior class directly is not a good idea, so I will create an inherited class that enhances the postSave method rather than changing it directly. And than there is the logic to be added for removing the tag. It will simply check whether the saved user_id is the same as the id of the current user. That’s it.

I’m quite happy with my little learning experience as the whole concept of mixins and behaviors did not cross my road before. But it is so useful, that I probably enhance some of my plugins (e.g. for images) into behaviors. Nice exercise that will be. And I can only encourage anyone to stick his nose into those slightly more advanced topics as they will benefit you in many ways.

And for the nutrition site, the next problem to be solved will be finding the best way to implement a Contend Delivery Network for better response times of the Frontend.

Use a Highlighter on this page

Transcript of Symfony Plugin Developers Day IRC log

Use a Highlighter on this page

Pidgin crashes with ‘Segmentation fault’ (Solved!)

Pidgin is a multi-protocol chat client that I use basically for my MSN contacts only. It did its job pretty well so far. Until some weeks ago after an update it stopped working. I never really figured out what the problem is as I merely use Skype, but now needed to contact some people using the MSN protocol. So I started a little investigation and found a work around.

UPDATE 16/07/2008: There are two solutions described here, the second one comes from a comment and is actually – if it works – the much nicer Read more »

Use a Highlighter on this page

Since upgrading to Ubuntu 8.04 I am running Firefox in its latest version 3. At the beginning it was the beta 5, in between RC2 and now the final version. At the beginning I found some issues with some websites, for example the typo3 backend and simply ignored it and used Opera instead. But it seems there is more behind it than just initial hickups as I found more and more sites apparently incompatible to the new Javascript engine.

Read more »

Use a Highlighter on this page

Newspaper Publishing – comparison of success and failure

Newspapers as a medium for news and advertising have a long history and challenged some competition from Radio, TV and now the internet. All had and have their effect on circulation, which is itself affecting the amount of money Publishers are making with advertising and their general health. So I had a glance on different developments of newspaper circulations and found two extremes in the US and Australia. The US with rather old-school management due to the strong segmentation of the market and little competition and two modern Publishers in Australia competing in all media areas against each other. So let’s have a look how these two scenarios differentiate and influence the portfolio and competitiveness of the industry.

Read more »

Use a Highlighter on this page