Field and Method Literals
Matthew Adams
matthew at matthewadams.me
Mon Nov 21 13:59:55 PST 2011
I'm not quite sure what that means. Can you please elaborate?
On Mon, Nov 21, 2011 at 11:39 AM, Brian Goetz <brian.goetz at oracle.com>wrote:
> Don't worry, this road is already well explored.
>
>
> On 11/21/2011 10:34 AM, Matthew Adams wrote:
>
>> 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<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.**
>>> AnnotationSessionFactoryBuilde**r;
>>>
>>> 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 AnnotationSessionFactoryBuilde**r()
>>> .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.**
>>> AnnotationConfigApplicationCon**text;
>>>
>>> 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) {
>>> AnnotationConfigApplicationCon**text ctx = new
>>> AnnotationConfigApplicationCon**text();
>>> 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<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