Field and Method Literals

Chris Beams cbeams at vmware.com
Mon Apr 18 01:40:25 PDT 2011


On Sun, Apr 17, 2011 at 8:14 PM, Collin Fagan <collin.fagan at gmail.com<http://gmail.com>> wrote:

But more to the point what is Chris actually asking for? Is it just to be able to use static method references with annotations?

This thread originated on coin-dev (thanks Rémi for cross-posting here), but I believe my original use case didn't make it over.  Let me reiterate and expand.

Many will associate Spring with XML-based application configuration, but since Spring 3.0 we also offer a 100% Java-based solution for configuring dependency injection, application of advice, and the myriad other services and features of the Spring container.  The central artifacts in this support are user-defined "@Configuration classes".  A brief but practical example follows to provide context for our use cases.

package com.myco.app.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBuilder;

import org.hibernate.SessionFactory;

import javax.sql.DataSource;

import com.myco.app.domain.Foo;
import com.myco.app.service.FooService;
import com.myco.app.service.SimpleFooService;
import com.myco.app.data.FooRepository;
import com.myco.app.data.HibernateFooRepository;

@Configuration
public class MyApplicationConfig {

    @Bean
    public FooService fooService() {
return new SimpleFooService(fooRepository());
    }

    @Bean
    public FooRepsitory fooRepository() {
        return new HibernateFooRepository(sessionFactory());
    }

    @Bean
    public SessionFactory sessionFactory() {
        return new AnnotationSessionFactoryBuilder()
            .setDataSource(dataSource())
            .setSchemaUpdate(true)
            .setAnnotatedClasses(Foo.class)
            .buildSessionFactory();
    }

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .build();
    }

}


Such a @Configuration class may then used to bootstrap the application.  If we're dealing with a simple standalone Java application, doing so within a main method will suffice:

package com.myco.app;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.myco.domain.Foo;
import com.myco.app.service.FooService;
import com.myco.app.config.MyApplicationConfig;

public class Bootstrap {
    public static void main(String... args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(MyApplicationConfig.class);
        ctx.refresh();

        FooService fooService =  ctx.getBean(FooService.class);
        Foo foo1234 = fooService.findById(1234);
        System.out.println(foo1234);
    }
}


Now let's get to the business of method literals.  Notice again the Hibernate SessionFactory @Bean definition:

    @Bean
    public SessionFactory sessionFactory() {
        // ...
    }


The SessionFactory is being created by Spring here, and will be managed by the Spring container for the lifetime of the ApplicationContext bootstrapped in our main method.  Note however that its configuration is not yet complete - it is important to call a SessionFactory's close() method on application shutdown in order to manage resources properly, and Spring provides a mechanism to allow users to specify this with the 'destroyMethod' attribute of the @Bean annotation:

    @Bean(destroyMethod="close")
    public SessionFactory sessionFactory() {
        // ...
    }

You can see the problem - 'close' must be specified as a string due to lack of method literal support in the language.  Far more desirable would be:

    @Bean(destroyMethod=SessionFactory#close)
    public SessionFactory sessionFactory() {
        // ...
    }

Whether the user is referring to an instance method or static method is, from the framework's point of view, immaterial.  We simply wish to provide the user with an IDE-friendly mechanism to execute a method during the destruction phase of the bean lifecycle.  We can do this already, but it requires stringification of method names.

This is certainly not our only use case, but in the interest of brevity I'll leave it here, noting that our use cases are not limited to method literals within annotations; such syntax would be useful within many contexts.  For a non-Spring example, consider the case of JPA 2's Criteria API, which is crippled by the lack of field literals in the language.  Its use is so cumbersome that the QueryDSL project has become quite popular in conjunction with JPA, as they take an APT-based code gen approach that effectively approximates the functionality of field literals [1].  Again, I find the utility of field and method literals self-evident, even obvious.  It is certainly not a Spring-specific itch we wish to scratch here, but rather to champion a generally useful addition to the language.

Are there fundamental objections to such support?  Does prior art in Project Lambda already encompass these use cases?  We'd be interested in hearing what next steps are necessary to help make this a reality in JDK 8 and how we can help.

Thanks,

- Chris

[1]: http://source.mysema.com/forum/mvnforum/viewthread_thread,49




More information about the lambda-dev mailing list