Delegates, Protocols, and Optional Methods

June 5, 2011

In my iOS app, I have a lot of places where I show a modal view, and that view needs to have access to the view that opened it. To implement this connection, I’m using the concept of “delegates,” where one object has another object that it can call methods on. I created a protocol called ModalDelegate that defined the methods that these modals could call on their parent views. However, the way I implemented this caused a lot of compiler warnings. I just now figured out how to fix these, but the answers were difficult for me to find, so I figured I’d post them here.

First, it was my understanding that using id as a variable type was the standard Objective-C way to keep a reference to an object that can be of any class–the equivalent of the Java class Object, but more widespread in use. However, when I stored my delegate as an id, then tried to call a method on it, I received a warning that that method might not be defined. I could have cast the id to the appropriate type, but that seemed like it shouldn’t be necessary.

So, instead, I changed the type of the variable from id to ModalDelegate, the name of the protocol I created. This seemed intuitive to me from the way Java interfaces are used, and the compiler didn’t reject that variable naming. However, I got a similar warning: that method might not be defined. When I looked into it, I discovered that wasn’t the right syntax to use for a protocol at all. The right type for the variable was id <ModalDelegate>–in other words, an object of any type, but one that conforms to the ModalDelegate protocol. Also, instead of referring to @class ModalDelegate; in my header file, I needed to refer to @protocol ModalDelegate;.

The one remaining warning I was getting after this was that my classes weren’t implementing all the methods on the ModalDelegate protocol. The reason for this was that different views needed to have different methods called on them, and I didn’t want to have a separate delegate definition for each. So there were lots of methods in ModalDelegate, and each class that conformed to the protocol only implemented some of them. Of course, this isn’t how protocols are meant to work, but I didn’t see an alternative. But finally I found it: optional methods on protocols. I just add an @optional above all the methods that I want to be optional, and then the warnings went away. For my protocol, I actually wanted all the methods to be optional.

I don’t think this is a violation of the concept of the protocol, precisely because it removes all the warnings I had above. My modal view can call methods on its delegate without compiler warnings, because it knows it should have an id and that it may have a method of the appropriate type. The alternative would be to simply have an id and accept the warnings, or else use performSelector:withObject:, but those seem like overkill for the situation I’m in. The other alternative would be to implement each of the protocol methods and leave some of them as empty implementations. But all of these seem like overkill for my situation. With a protocol with optional methods, I’ve clearly defined for the compiler what I’m doing, and its lack of warnings assures me that I don’t have any typos.


Returning Grails Validation Errors for Ajax Calls

January 6, 2011

I’m using Grails to create a REST service, and its built-in JSON formatting makes receiving and returning objects easy. When I get validation errors, I’d like to return the errors in JSON in a format that’s easy to use by my client. With a web client, Grails (and most other validation frameworks) by default outputs a list of human-friendly error messages. Ideally, what I’d like to return from my REST service is a list of strings, where each string is one field error.

Incidentally, REST’s HTTP status codes make it easy to distinguish when I’m returning objects vs. error messages. If I return a 200 or 201 status code, it’s success, and my client should expect an object from my data model back. If I return a 500 status code, my client should expect a list of error strings back.

It took me a little poking around in javadocs and Grails source to figure it out, but here’s the syntax that will work:


response.status = 500
render myGormObject.errors.allErrors.collect {
    message(error:it,encodeAs:'HTML')
} as JSON

Running JUnit 4 Tests in Maven

December 8, 2010

I was trying to convert my JUnit tests to JUnit-4-style annotations, and they would run fine individually in Eclipse, but the Maven Surefire plugin wasn’t running them properly. Seems that it was running them using a JUnit 3 runner, because it detected tests by finding methods with “test” at the start of the method name, but ignored @Test and @Before annotations.

I read a number of articles online about how to fix this, but what they said didn’t work. Eventually, I found that I had to add the following entry exactly (can’t omit junitArtifactName, or add a version number to it).


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<includes>
<include>**/Test*.java</include>
</includes>
<junitArtifactName>junit:junit</junitArtifactName>
</configuration>
</plugin>
</code>


Installing Java 6 JDK on Ubuntu

October 3, 2010

None of the posts I found on this worked quite right, so I’m writing up what I did here for future reference.


sudo apt-get update
sudo apt-cache search java6

When I did this, the results I got included:


default-jdk
default-jre
default-jre-headless
openjdk-6-jdk
openjdk-6-jre
openjdk-6-jre-headless

If I’m interpreting it right, that means the Sun JDK is not available for installation via apt-get, at least the way I have it configured. But people said that the OpenJDK works fine too. So I decided to install it. It seems that specifying “default-jdk” just installs “openjdk-6-jdk” anyway:


sudo apt-get install default-jdk

When this completed, /usr/bin/java was set up for me. But I did have to add a JAVA_HOME environment variable to my .bashrc file:


export JAVA_HOME="/usr/lib/jvm/java-6-openjdk/jre"

After that, I was set to go.


Changing the Grails Default Server Port

March 9, 2010

The Grails tutorial I read said provided instructions for changing the default server port from 8080 to some other value, so that you would not need to specify an alternate server port every time you run-app. It said that you should open $GRAILS_HOME/scripts/Init.groovy and look for a line setting the value of serverPort.

The problem is that this tutorial was written in 2008, and while you wouldn’t think that much would have changed since then, apparently the Grails config files have been refactored. Init.groovy now appears to be a much higher-level file, and serverPort isn’t specified in it.

After searching the Grails directory, I found out that the new file to edit is $GRAILS_HOME/scripts/_GrailsSettings.groovy. Open it and look for the following line:

serverPort = getPropertyValue("server.port", 8080).toInteger()

I believe the getPropertyValue method checks properties sent in via the command line or configured in some other way. If it’s not set, though, it uses the second parameter as the default value. Change it from 8080 to some other port, like 9090, and the next time you run-app you’ll be running on the new port instead


List of All Grails Validation Constraints

February 22, 2010

For some reason, Grails decided to delete their published list of all validation constraints. This official-sounding page just sends you to the reference docs, and its validation page gives the unhelpful message that

A complete reference for the available constraints can be found on the reference guide

I’m not sure what other reference guide this could be referring to, not to mention what it would mean for this information to be found “on” the reference guide, as opposed to “in” it.

Update: @mr_paul_woods sent me to the Grails docs and told me to look in the sidebar. Turns out that I wasn’t supposed to click Validation on the right pane, but rather find “Constraints” in the unrelated left pane. There’s no way to get this list on a page by itself, so here they are to be helpful:


Securing DWR

September 25, 2009

DWR is a great Ajax framework. One of the things that makes it easy is its web interface for generating JS interface files. However, that’s not something you probably want to expose to end-users. For one thing, it gives you an easy GUI interface to call any method you have with any parameters they like – a great tool for hacking!

Now, ultimately your server-side code should ensure security. But it’s also good to hide this DWR published interface. Here are some security settings you can add to your web.xml file to hide them, while still allowing DWR calls to go through:

<security-constraint>
<display-name>Protect DWR</display-name>
<web-resource-collection>
<web-resource-name>Test</web-resource-name>
<url-pattern>/dwr/test/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<web-resource-collection>
<web-resource-name>Index</web-resource-name>
<url-pattern>/dwr/index.html</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>Forbidden</description>
<role-name>Forbidden</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>

What this code does is put a security wrapper on /dwr/index.html and the /dwr/test directory. It’s requiring a role called “Forbidden,” and since you don’t define any users with that role, it effectively prevents anyone from getting to it. However, /dwr/call/ is kept free, so true DWR calls can make it through.


HttpServletRequest Demystified

April 17, 2009

Today is about the tenth time I’ve needed to redirect to a slightly modified version of the current URL. So, I have to piece together a URL from pieces in an HttpServletRequest. And I can never remember which piece is which. I know, I know, the difference between “servletPath” and “pathInfo” should be intuitively obvious to me. So now, for the last time, here is what the pieces mean, for an example URL: http://www.myserver.com:8080/appname/servletname/my/path?name=value

  • protocol – “HTTP/1.1″ (you’ll have to convert this back to http or https, for example)
  • serverName – “www.myserver.com”
  • serverPort – 8080
  • contextPath – “/appname”
  • servletPath – “/servletname”
  • pathInfo – “/my/path”
  • queryString – “name=value”

Not looking at all of these values now, so some might be slightly off – please post a comment to correct me.


Sample App 0.1.1 Released

February 11, 2009

I’ve just uploaded a minor patch to Sample App. This fixes some errors in the production build targets, and adds more thorough JavaDoc and YUI Doc.

sample-app-0.1.1.zip – 20.6 MB

You can also find out more about Sample App.


Sample App 0.1 Released

February 10, 2009

I’ve just posted a Java webapp called “Sample App” (until I can think of a better name for it). The goal for this webapp is to be a project template using industry-standard libraries and best-practices for full-stack Java application development, from a high-performance rich client tier, back to the database. There’s nothing particularly revolutionary about it, but it’s hard to find this particular combination of features – especially a combined rich frontend and backend. It’s released under a BSD license.

sample-app-0.1.zip

Check it out, take what’s helpful to you, and improve on the rest!

Features

  • Client
    • Logging (YUI Logger)
    • Combination of assets to save on HTTP requests
    • CSS sprites automatically generated (SmartSprites)
    • Minification (YUI Compressor)
    • Ajax requests (YUI Connection)
    • Strict presentation logic boundary (JSTL)
    • Copy in properties files
    • Object-oriented JavaScript
    • Event binding performed by JavaScript, not in markup
  • Server
    • Separation of business logic and webapp into distinct projects
    • Dependency injection (Spring)
    • Unit testing (JUnit)
    • MVC (Struts configured via Spring)
    • ORM (Hibernate)
    • Logging (Log4J)
    • Separate Business Logic and DAO tiers
  • Build
    • Separate build targets for dev and prod environments, changing config files, adding additional JS, and enabling/disabling logging and minification
    • Run on local box from a bare checkout using a build target, without any additional configuration or native code (Jetty, HSQLDB)

Requirements:

  • JDK 1.5 or above
  • Ant 1.6.5 or above

Getting Started:

Download the zip file above, expand it, go to sample-webapp/build, and run ant. This will run the default target run-dev. The app will then be accessible on your local computer at http://localhost:8080/sample-webapp/


Follow

Get every new post delivered to your Inbox.

Join 525 other followers