Logging Done Right on AppEngine for Java

Posted on : 2011-04-06 | By : Sam Edwards | In : App Engine, Frameworks

Tags: , , , , ,

0

I have found that using slf4j is the best bet when logging with App Engine for Java. You log against their API and then you provide a binding to any of the supported logging frameworks at runtime. In the case of App Engine, java.util.logging is used primarily, however is isn’t as flexible as log4j so in order to get around this, I use a slf4j and a log4j binding during development and a jdk (java.util.logging) binding for releases/deploys. This means that all my logs will be accessible through the App Engine administrative panel.

Here is the <profiles> configuration of our Maven pom.xml file in order to setup a defult “development” profile with log4j and a “release” profile for deploys to App Engine.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <properties>
    <slf4j.version>1.6.1</slf4j.version>
    <log4j.version>1.2.16</log4j.version>
  </properties>
  ...
  <profiles>
    <profile>
      <id>development</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <dependencies>
        <!-- LOG4J logging -->
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${slf4j.version}</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>${log4j.version}</version>
        </dependency>
      </dependencies>
    </profile>
    <profile>
      <id>release</id>
      <dependencies>
        <!-- Java Util Logging -->
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-jdk14</artifactId>
          <version>${slf4j.version}</version>
        </dependency>
      </dependencies>
    </profile>
  </profiles>
</project>

logging.properties
This should go at /WEB-INF/logging.properties or wherever is specified in your appengine-web.xml file in this line:

<!-- Configure java.util.logging -->
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
</system-properties>
.level = WARNING

com.YOURPACKAGENAME.level=ALL

log4j.properties
This should go in the root of your source directory. So in a maven project in /src/main/java/log4j.properties

# console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%-5p: %m  at %C.(%F:%L) on %d{ISO8601}%n

#Get Stuff I want
log4j.category.com.YOURPACKAGENAME=ALL, console

Google IO 2011 Last Call Google Maps/Geo Entry (Tour-IO)

Posted on : 2011-03-25 | By : Sam Edwards | In : App Engine, Events, Geo, Maps, Mobile

Tags: , , , , ,

0

I (@HandstandSam) went ahead and personally entered the Google Maps/Geo Challenge yesterday and hacked together http://tour-io.appspot.com. Hopefully it’ll win me a ticket to Google I/O 2011.

It took a while for me to figure out the “Record” part of the contest (Contest Instructions are below) and therefore I didn’t really get to do much with “recommending”. However, I do allow you to view others tours by category! A note, only “tours” with more than 1 point are listed. I had a lot of “test” tours with 1 point (aka my non moving laptop) and didn’t want those to show up as tours.


The source for this project is available on GitHub and here are the readme contents:

This app was created in less than a day and allows you to record a “tour” via a mobile browser (Android and iPhone). You name the tour and select a category. Once you are finished with the tour, the tour is listed in the directory for others to view.

LIVE VERSION

http://tour-io.appspot.com

TECHNOLOGIES USED

  • Google Maps
  • jQuery
  • Google App Engine for Java
  • Objectify
  • Gson
  • JSON
  • SLF4J

CONTEST INSTRUCTIONS

Congratulations! You have qualified for Round II of the Google Maps/Geo challenge. Starting from now, you will have until 4:00 P.M. PDT on March 24 to complete the following coding challenge.

Walking Tours of San Francisco Build a mobile web app to record and recommend walking tours around the sights of San Francisco for I/O attendees who have never been to the city before

Extra points for incorporating: Street View Showing the elevation profiles for each walk Implementing a Styled Map Using fusion tables

Submission Guidelines: Please ensure that you read the following carefully. Incomplete submissions will be disqualified. Complete the form at http://goo.gl/9YCTI to submit a live implementation of your code (URL) by 4:00 P.M. PDT on March 24. Be sure to include the confirmation number at the top of this email. Email a .zip file of the source code to *********@google.com. Make sure the subject line of the email reads: Google Maps/Geo, Round 2 – [Last Name, First Name]

Your submissions, (1) and (2), must be received within 10 minutes of each other and no changes are permitted to your code after the submission period. We will be using the live implementation of your code for judging and verifying this against the code you emailed to ensure that no changes were made to the code after the contest period.

Good luck!

App Engine, Stop Adding JARs I Do Not Use!

Posted on : 2011-03-23 | By : Sam Edwards | In : App Engine

Tags: ,

0

It looks like you can modify some settings to get rid of enhancing and libs you don’t use by editing these properties. Anyone had any luck with this?

filesCopiedToWebInfLib=appengine-api-1.0-sdk-1.4.2.jar|appengine-api-labs-1.4.2.jar|appengine-jsr107cache-1.4.2.jar|jsr107cache-1.1.jar|datanucleus-appengine-1.0.8.final.jar|datanucleus-core-1.1.5.jar|datanucleus-jpa-1.1.5.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-eb.jar
ormEnhancementInclusions=src/

Don’t Leave an Empty ‘src’ Attribute on an HTML Image Element

Posted on : 2011-03-13 | By : Sam Edwards | In : Tips

Tags: , ,

0

I just spent the last while tracing down a bug where my server was getting called twice everytime a certain page was visited. I finally realized it was because I had

was using JavaScript to dynamically put in the ‘src’ later. This caused the server to make another request for the current page, and therefore the page was getting loaded twice!!!

Thankfully I found it! Don’t let this happen to you!

Google SEO Made Easy

Posted on : 2011-03-11 | By : Sam Edwards | In : Tips

Tags: ,

0

Google has an updated version of their Search Engine Optimization (SEO) guide. Check it out.

Remove Extra Whitespace from JSP Files!

Posted on : 2011-03-04 | By : Sam Edwards | In : Tips

Tags: , ,

0

Just add in the trimDirectiveWhitespaces=”true” and you’re golden!

In order to get this to work You’ll need to do three things…

  1. You must be using at least webapp vesion 2.1 or newer. Specify this in your web.xml file in the tag with version=”2.5″
  2. If you are using App Engine, you must be using version 1.4.2, 1.3.8 did not support this.
  3. <%@ page isELIgnored="false" trimDirectiveWhitespaces="true" contentType="text/html;charset=UTF-8"%>

Getting Started with the Facebook JavaScript API

Posted on : 2011-03-02 | By : Sam Edwards | In : APIs, Facebook

Tags: , , , ,

0

Post will continue to be updated.

Some great examples are available on GitHub



  
  
    

  
  

Connect JavaScript - jQuery Login Example

More documentation is available at http://developers.facebook.com/docs/reference/javascript/fb.api/

Using Amazon S3 with Google App Engine for Java

Posted on : 2011-02-15 | By : Sam Edwards | In : App Engine, Tips

Tags: , , , , , ,

0

Update: (2011.03.16) – Github Link Updated

Amazon S3 is a fantastic way to store static files, but when you try to use their Java SDK on Google’s App EngineFAIL!

Soo, after a day of hitting my head against the wall, I finally had some success by combining multiple projects. The result: s3-simple-appengine on GitHub

The code is a mix of these libraries:

jets3t and Amazon’s SDK are great but they use the Apache Commons http client which doesn’t work 100% on Google App Engine. This is due to restrictions… namely, no threads, no sockets, and… other restrictions…

The library I’ve thrown together allows me to do “PUT” requests and upload blobs from the datastore, as well as create signed URLs which are the two things I needed currently.

//Create an S3Store Object and Set the Current Bucket
S3Store s3 = new S3Store(Constants.S3_DEFAULT_HOSTNAME, ACCESS_KEY, SECRET_KEY);
s3.setBucket("my-bucket");

//Sign an S3 URL
String signedUrl = s3.createSignedGETUrl(objectKey, validForInSeconds, isHttps);

//Upload Binary Data to S3 (i.e. From the AppEngine Blobstore, etc)
final Map<String, List<String>>() headers = new HashMap<String, List<String>>();
headers.put("Content-Type", contentType);
s3.storeItem(key, bytes, Constants.ACL_PUBLIC_READ, headers);

Secrets of GWT [Slides] – David Chandler

Posted on : 2011-01-31 | By : Sam Edwards | In : App Engine, Events, Tips

Tags: ,

0

David Chandler, a member of the Google Web Tookit (GWT) team at Google, and author of the blog turbomanage.wordpress.com spoke at the National Capital Area Google Technology User Group Meetup on January 18th and spoke about both GWT and Google App Engine.

Here are his slides from the presentation:

Updating App Engine Cron Jobs Manually

Posted on : 2011-01-28 | By : Sam Edwards | In : App Engine, Tips

Tags: , ,

0

I have been having issues updating the cron jobs for http://FoursquareBrands.com and needed to update them. Because the Java update kept giving me problems, went another route. I used the python command to update the application’s cron jobs.

After reading the Python documentation, I found out you can do this by running the following command (after adding in the two files mentioned below in your WEB-INF directory):

Use the terminal to navigate to your WEB-INF directory and run the following command:

appcfg.py update_cron .

This allowed me to update my cron jobs when I couldn’t through Java.

application: 4sqbrands
version: 11
runtime: python
api_version: 1

handlers:
- url: /(.*)
  static_files: static/\1
  upload: static/(.*)
cron:
- description: Follows new Brands when Discovered
  url: /cron/hourly
  schedule: every 1 hours synchronized

- description: Collects Brand Follower Stats Daily at 12:05am Pacific Time (Same as Google Analytics)
  url: /cron/daily
  schedule: every day 00:05
  timezone: America/Los_Angeles

- description: Sends out a Tweet of New Brands at 7:00am
  url: /cron/dotweet
  schedule: every day 7:00
  timezone: America/New_York

- description: Sends out a Tweet of New Brands at 7:00pm
  url: /cron/dotweet
  schedule: every day 19:00
  timezone: America/New_York