Field and Method Literals

Matthew Adams matthew at matthewadams.me
Mon Nov 21 07:34:22 PST 2011


I reiterate Chris's suggestion for method and field literals, and caution
Project Lambda to carefully consider the syntax.  There is an ambiguity
that I want to make sure that we're not overlooking here that would cause
problems with various proposed method/field literal syntaxes.

Currently, Chris's examples and Project Lambda's "::" method reference
syntax introduce an ambiguity when referring to a method that has the same
name as a field.  See my post on this at
http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-November/000293.html for
more detail on my suggestion.  In short, though, here's the jist (I'll use
"::", but I still prefer "#" as the method/field literal operator).
 Consider the following class:

public class Foo {
    private boolean close;
    @Goo(hoo="loo") public Foo() { /* ... */ }
    /* A */ public void close() { /* ... */ }
    /* B */ public void close(int timeout) { /* ... */ }
}

If member literal syntax is to be supported now or in the future,
"Foo::close" is ambiguous.  What should the compiler do here?  Interpret
the expression as a field or method reference if it's not ambiguous?  I
think I'd prefer a syntax that requires parens for method references:

Foo::close // field
Foo::close() // refers to method A above
Foo::close(int) // refers to method B above

This also allows me to refer to constructors, BTW:

Foo::()

And annotations:

Foo::()@Goo

And annotation properties:

Foo::()@Goo(hoo)

I reiterate also that the persistence specifications JDO & JPA can benefit
from such constructor, method & field literals.  In their absence, projects
like QueryDsl, Hibernate's Criteria, JPA's Criteria, and JDO's proposed
typesafe query APIs have been created, using generated classes to provide
the typesafe references that are needed.

-matthew


On Mon, Apr 18, 2011 at 3:40 AM, Chris Beams <cbeams at vmware.com> wrote:

> On Sun, Apr 17, 2011 at 8:14 PM, Collin Fagan <collin.fagan at 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
>
>
>


-- 
@matthewadams12
mailto:matthew at matthewadams.me
skype:matthewadams12
yahoo:matthewadams
aol:matthewadams12
google-talk:matthewadams12 at gmail.com
msn:matthew at matthewadams.me
http://matthewadams.me
http://www.linkedin.com/in/matthewadams


More information about the lambda-dev mailing list