Java Persistence - finders and named queries

865 views
Skip to first unread message

Petr Jiricka

unread,
Dec 18, 2009, 3:13:03 PM12/18/09
to project...@googlegroups.com
Hi,

I would like to ask what people think about the following idea. There
could be an annotation that generates an implementation of a JPA
finder, or a named query. E.g. for an auto-generated named query, I
would put the following to an entity class:

@Entity
@AutoNamedQueries({
@AutoNamedQuery("Customer.findAll"),
@AutoNamedQuery("Customer.findByCustomerId"),
@AutoNamedQuery("Customer.findByZip")
})
public class Customer {
...
}

After transformation, it would generate the following:

@Entity
@NamedQueries({
@NamedQuery(name = "Customer.findAll", query = "SELECT c FROM
Customer c"),
@NamedQuery(name = "Customer.findByCustomerId", query = "SELECT c
FROM Customer c WHERE c.customerId = :customerId"),
@NamedQuery(name = "Customer.findByZip", query = "SELECT c FROM
Customer c WHERE c.zip = :zip")
})
public class Customer {
...
}

I.e. the actual implementation of the query would be automatically
generated based on the query name.

For finders, one would write the following in a DAO (facade) class:

@AutoFinders(forEntity=Pet.class, finders={
@AutoFinder("findByNameAndWeight")
@AutoFinder("findByOwner")
@AutoFinder("findByTypeAndNameLike")
})
public class PetFacade {
...
}

This would generate the following methods in the PetFacade class,
including the complete implementation:

public class PetFacade {

public List<Pet> findByNameAndWeight(String name, Float weight) {
Query q = em.createQuery("SELECT Pet FROM Pet AS pet WHERE
pet.name = :name AND pet.weight = :weight");
q.setParameter("name", name);
q.setParameter("weight", weight);
return q.getResultList();
}

public List<Pet> findByOwner(Owner owner) {
Query q = em.createQuery("SELECT Pet FROM Pet AS pet WHERE
pet.owner = :owner");
q.setParameter("owner", owner);
return q.getResultList();
}

public List<Pet> findByTypeAndNameLike(PetType type, String name) {
name = name.replace('*', '%');
if (name.charAt(0) != '%') {
name = "%" + name;
}
if (name.charAt(name.length() -1) != '%') {
name = name + "%";
}
Query q = em.createQuery("SELECT Pet FROM Pet AS pet WHERE
pet.type = :type AND pet.name LIKE :name");
q.setParameter("type", type);
q.setParameter("name", name);
return q.getResultList();
}

}


Again, the implementation would be created based on the finder name
itself. As you see, the finder name pattern does not need to be
limited only to single column name, but it could understand the
combination of column names, logical operators, qualifiers such as
LessThan, NotEqual, Between, Like etc. Also, it could also generate a
variant of the finder with int firstResult, int maxResults parameters,
resulting in something like:

public List<Person> findAll(int firstResult, int maxResults) {
return em.createQuery("select o from Person o").

setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
}

(BTW, the above examples use the Java Persistence Query Language, but
it could just as well generate Criteria API calls that were added in
JPA 2.0.)

This idea is inspired by the dynamic finders in Grails, which work in
a similar way:
http://www.grails.org/doc/1.1.x/guide/single.html#5.4.1%20Dynamic%20Finders

I am attaching a skeleton of the AutoFinder and AutoNamedQuery
annotations and the corresponding Javac handlers (just a first sketch
and a proof of concept, does not do much yet). The attached
annotations also use a slightly different syntax than outlined above.

What do you think about this application of Lombok?

Thanks,
Petr

AutoFinder.java
AutoNamedQuery.java
HandleAutoFinder.java
HandleAutoNamedQuery.java

Jacek Furmankiewicz

unread,
Dec 18, 2009, 3:20:39 PM12/18/09
to Project Lombok
For JPA entities, anything that helps is good. Especially the
cumbersome syntax for mapping an @Id to a Oracle sequence (very
convoluted for something that should be so simple).

But for the finder, I'm not sure if it's such a big hit, because it's
raw JPA-specific.
Most server-side apps (at least the ones I've seen) are Spring-based,
so you would be probably using the Spring JpaTemplate class for all
the finder logic.

Hence, your EntityManager-specific code may not be applicable for many
apps...

Reinier Zwitserloot

unread,
Dec 18, 2009, 4:35:27 PM12/18/09
to Project Lombok
It's interesting how much traffic lombok gets in regards to JPA-
related issues.

I'll split up my thoughts into two replies. First, on JPA boilerplate
in particular, and then (as I'll be concluding this is best left to
lombok plugins), on how to distribute lombok plugins better than the
current situation.

But first, JPA boilerplate:

I'm not entirely certain lombok is the right place for this stuff; the
sheer amount of interesting features that have been paraded on this
newsgroups as being 'boilerplatey' in nature suggests to me what's
needed instead is some sort of DSL, preferably one that gets picked up
automatically by the java compiler.

There's so much effort going on in this space, it's hard to come up
with something for lombok now that'll stand the test of time. For
example, I know Alex Buckley had quite a bit to say during the devoxx
BOF on java7 features about a JVM 'meta compiler' capable of compiling
any number of source files written in any number of source languages
all at once, solving interdependencies between different source files,
even if written in different languages, automatically. If something
like that existed and/or javac was extended with a feature for other
language compilers to 'plug in', generate dependency-free TypeMirror-
like objects in a first round, and actually compile on the second,
then such a DSL could be written directly, and with mostly the same
benefits as lombok annotations: it "just works", seamlessly, in all
your build processes and presumably the TypeMirror concept is simple
enough to generate so that IDEs can work with this the way they work
with java code: As-you-type, continuously integrated, with
dependencies sorted out automatically.

That's the utopia vision. The fact that Annotation Processing
integration in editors is pretty bad (I hope lombok is making some
impact on rectifying this, but still), and that API has been around
for quite a while at this point. It's also fairly well designed. There
are some issues about performance (the Annotation Processing API has
full resolution available, and doing full resolution on an enormous
source tree is just not feasible), but at the very least run-
processors-on-save is performance-wise perfectly doable and only
eclipse does this, and not particularly well.

Still, even if that is as of now still a pipe dream, it contrasts
rather sharply to what the situation would be if lombok offered these
features. With lombok, you'd have iffy resolution getting in the way
(thank eclipse for that), and you'd have to express the DSL entirely
in annotations.


One could argue that JPA annotations already are a DSL. If I
understand JPA correctly, you are desugaring a bunch of annotations
into a bunch of different, more verbose annotations. Using lombok to
do this feels like the wrong place for a much simpler reason: Why not
add @AutoNamedQuery to JPA itself? It's hard to change such a
widespread established standard as JPA, but I see nothing backwards
incompatible about doing this; it can even be implemented in the
generic JPA interface layer without burdening JPA implementors with
the need to add it.

Don't get me wrong; even with the kludge of using annotations to write
something that has ceased to look anything like a simple POJO,
@AutoNamedQuery is pretty cool!


Going back to DSLs, given that Lombok is already plugged into a
relatively early step in the compilation process, why doesn't lombok
extend into this territory? I'm not entirely sure Lombok's current
javac deployment mechanism runs early enough to catch files that look
absolutely nothing like java, but perhaps we can find a way. At worst
we'll have to resort to the simple but hacky 'magic comment' strategy.


However this happens, one thing is fairly clear to me: JPA's needs are
very specific and almost always unsuitable for anywhere else. For
example, a recurring issue that we keep flagging with 'WontFix' in the
issue tracker is to make the equalsAndHashCode implementation use an
instanceof check instead of a straight class comparison. This is the
right thing to do for JPA (due to proxy classes). It's the wrong thing
to do anywhere else (because you can't guarantee transitivity that
way). Thus, while I confess I haven't used JPA in any real world
project, so I might be way off here, it seems to me that lombok-based
JPA boilerplate busting annotations should be very clearly marked as
being useful only in combination with JPA.


Transformations that make sense only in the context of a library
should probably not be piled into the core lombok distribution -
though JPA may be popular enough to break this rule, especially if we
create a special lombok.jpa package for it. To decide what to do, it
helps to know how easy it is to plug into lombok. Which I'll deal with
in the next post (I'll start a new topic for that).

Petr Jiricka

unread,
Dec 21, 2009, 11:21:02 AM12/21/09
to project...@googlegroups.com
Hi Reinier,

thanks a lot for your elaborate and insightful reply.
See more below.

With respect to NetBeans, this is a very hot topic for the upcoming
NetBeans 6.9: http://wiki.netbeans.org/
EditorPlan69#Annotations_support. We can expect some new development
in this area in the coming weeks and months.

>
> Still, even if that is as of now still a pipe dream, it contrasts
> rather sharply to what the situation would be if lombok offered these
> features. With lombok, you'd have iffy resolution getting in the way
> (thank eclipse for that), and you'd have to express the DSL entirely
> in annotations.
>
>
> One could argue that JPA annotations already are a DSL. If I
> understand JPA correctly, you are desugaring a bunch of annotations
> into a bunch of different, more verbose annotations. Using lombok to
> do this feels like the wrong place for a much simpler reason: Why not
> add @AutoNamedQuery to JPA itself? It's hard to change such a
> widespread established standard as JPA, but I see nothing backwards
> incompatible about doing this; it can even be implemented in the
> generic JPA interface layer without burdening JPA implementors with
> the need to add it.

The truth is that JPA as a technology *is* quite 'boilerplatey'. There
is a lot of code that people have to repeat over and over when
creating data access objects. This code should be simplified away. But
you have a good point that Lombok may not be the best approach to
address this, and the implementation of things like @AutoNamedQuery
could/should just as well be addressed at the level of JPA, or an
independent library on top of JPA.

When I searched the web, I found out that a couple projects indeed
already try to do that, such as this one: http://redmine.synyx.org/projects/show/hades
. The first thing to do is to abstract common runtime code to a
library or the standard itself, and then we'll see whether there is
something left for Lombok to do.

I agree that many things would be much easier if it was possible to
integrate them at the language level, and if we had an even much
better (meta)compiler than javac is today, but as you say, this is the
utopia. Lombok should be focused on practical problems that can be
addressed right now using today's tools, not on problems we may be
able to solve using technologies that will be ready in 2-3 years.

I agree any support for JPA should not be at the very heart of Lombok
- it should be a separate extension.

Petr

>
>
>
> On Dec 18, 9:20 pm, Jacek Furmankiewicz <jace...@gmail.com> wrote:
>> For JPA entities, anything that helps is good. Especially the
>> cumbersome syntax for mapping an @Id to a Oracle sequence (very
>> convoluted for something that should be so simple).
>>
>> But for the finder, I'm not sure if it's such a big hit, because it's
>> raw JPA-specific.
>> Most server-side apps (at least the ones I've seen) are Spring-based,
>> so you would be probably using the Spring JpaTemplate class for all
>> the finder logic.
>>
>> Hence, your EntityManager-specific code may not be applicable for
>> many
>> apps...
>

> --
> You received this message because you are subscribed to the Google
> Groups group for http://projectlombok.org/
>
> To post to this group, send email to project...@googlegroups.com
> To unsubscribe from this group, send email to
> project-lombo...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/project-lombok?hl=en

Petr Jiricka

unread,
Dec 21, 2009, 12:02:20 PM12/21/09
to project...@googlegroups.com

On Dec 18, 2009, at 9:20 PM, Jacek Furmankiewicz wrote:

> For JPA entities, anything that helps is good. Especially the
> cumbersome syntax for mapping an @Id to a Oracle sequence (very
> convoluted for something that should be so simple).
>

Hi Jacek,

I must say I don't have hands on experience with JPA with Oracle
database, so I don't know what you are referring to. This page does
not suggest that this is painful for cumbersome: http://wiki.eclipse.org/EclipseLink/Examples/JPA/PrimaryKey
Can you please elaborate on what you mean?

> But for the finder, I'm not sure if it's such a big hit, because it's
> raw JPA-specific.

Again, I am not sure what you mean - to me it seems auto-generating
JPQL/Criteria queries could be perfectly applicable also to Spring
apps, no? In fact, the framework I just mentioned in my previous mail: http://redmine.synyx.org/projects/show/hades
simplifies building queries in the context of Spring. In Spring, you
still have to write the query today, and this part could be
simplified, right?

> Most server-side apps (at least the ones I've seen) are Spring-based,
> so you would be probably using the Spring JpaTemplate class for all
> the finder logic.
>
> Hence, your EntityManager-specific code may not be applicable for many
> apps...

Sure, the implementation may need to be specific to several
environements, such as Spring, JavaEE6 (EJB 3.1, CDI), Seam, ..., but
the concepts are the same, I believe.

Petr

Jacek Furmankiewicz

unread,
Dec 21, 2009, 12:10:24 PM12/21/09
to Project Lombok
In my experience across a lot of different DBs, I've really run into 3
PK generation strategies

a) do it manually on the server-side via GUIDs
b) using autoincrement columns (most DBs support those). That is easy
in JPA
c) for Oracle (and PostgreSQL too I guess) use sequences.

However, the syntax for defining a sequence as a generator for a PK is
very verbose in JPA, e.g.:

@Id @Column(name = "F_SUBSCRIBER_PK")
@GeneratedValue
(strategy=GenerationType.SEQUENCE,generator="S_SUBSCRIBER")
@SequenceGenerator(name="S_SUBSCRIBER",sequenceName="S_SUBSCRIBER")
private Long primaryKey;

You have to define 2 separate annotations (@GeneratedValue and
@SequenceGenerator) and hook up the @GeneratedValue.generator to your
@SequenceGenerator.name

Why couldn't it just be:

@GeneratedValue
(strategy=GenerationType.SEQUENCE,generator="S_SUBSCRIBER")
private Long primaryKey;

I want a sequence and here's the sequence name. But instead I have to
define a whole separate annotation.
Lots of copy-n-paste in all of our JPA entities.

Jacek

David Goodenough

unread,
Dec 21, 2009, 12:31:04 PM12/21/09
to Project Lombok
One of the problems with JPA (and related projects like Db4o) is that
very few of them document the byte code enhancement that they do. I
suspect that many of them do things ever so slightly differently, but
with enough difference to make writing common code difficult. This is
an area that the JPA specifications have failed to address.

David

Reinier Zwitserloot

unread,
Dec 22, 2009, 10:56:27 AM12/22/09
to Project Lombok
Roel and I have a coding session planned for this evening, and we'll
take the time to discuss a few things.

In subsequent thoughts on this issue, I've mellowed my stance
somewhat. One of the things everybody tells me lombok 'does right' is
its pragmatism: A simple video on the frontpage, a no-fuss installer,
everything 'just works', etcetera. Plugins necessarily dilute this
pragmatism. JPA *IS* very popular, and as you say, it *IS* rather
boilerplatey. I can wax rhapsodic about how JPA sucks in many regards,
and that this JPA's fault, and that we need cool new technologies that
won't be here for years, but, that's disingenuous. The same thing can
be said for something like @Cleanup, which "is java's fault", and
which cool new future technologies (java7 coin) will fix.

The only two arguments of mine that really holds water here are:

- JPA is just a library in the end. Not _everybody_ uses it, so the
standard lombok stuff should not break or become confusing for others
just to accomodate it.

- Unlike lombok's current batch of annotations, any JPA-boilerplate-
busting annotation is unlikely to be fully grokked without at least
reading up on why they do what they do.

The first problem can be solved by creating a new lombok.jpa package
that contains JPA-specific annotations. The features page can explain
specifically what all annotations in this package are for, and people
trying to write @lombok.(ctrl+space) or import lombok.(ctrl+space)
won't be bothered with them either. The actual code required to make
any JPA-specific annotation 'work' is a drop in the bucket compared to
ASM and JNA which make up ~80% of the size of lombok.jar, so that's
certainly not a good reason to leave them out. This leaves as biggest
problem my own lack of JPA experience.

The second argument can be 'solved' in two ways: First of all, Roel
has been working on an eclipse plugin that shows the delomboked code
right in your IDE, which should definitely help folks understand
what's happening behind the scenes. A proof of concept of this was
written up in an hour or two, as 'delombok' already exists, and I'm
fairly sure it won't be too difficult build such a thing for netbeans
either. Also, JPA is fundamentally complex, and a leaky abstraction is
still useful if the goal is to simplify typing and encode patterns,
and not to simplify the amount of knowledge one needs to work with it.
It does mean a lot of effort has to be put in to make the JPA
annotations as logical as we can make them so people who look at
lombok.jpa-annotated stuff aren't completely baffled.

So, what, exactly, would JPA annotations look like?

There are many concerns I do know of:

- DB sequence-powered PK fields are a pain, as jacked showed.

- Due to proxy objects, equals should use instanceof, even though
that isn't compatible with transitivity, that is the lesser evil.

- empty constructor is always needed.

- equals in general. Exactly how does this work, anyway? The equals
generated by lombok pings the fields directly and does not use
getters, but in a proxy, these fields don't actually exist. Even if
somehow a field access resulted in the JPA system magically loading
this stuff in, a single equals() or hashCode() call could cause the
JVM to chug away for hours on end as it loads every bit of data in the
database in its quest to calculate 1 hashCode, if some of the fields
are db references. The pragmatic solution to this is to define
equality on PK, but that's not technically the sense of equality that
Object.equals()' javadoc suggests. If all you want to do is use db
proxies in hashmaps, though, it's probably the right answer. Equals/
hashCode in general with JPA objects seems like a complex problem with
no right answer to me, but perhaps there's something that makes the
most sense to use as a default. Do we need a DSL-ish thing for this?

- NamedQuery could be simpler (that's what started this thread).

What else, and how do we make an annotation-based DSL that does not
require resolution to accommodate all these situations?


On Dec 21, 6:31 pm, David Goodenough <david.goodeno...@btconnect.com>
wrote:

Moandji Ezana

unread,
Dec 22, 2009, 11:27:11 AM12/22/09
to project...@googlegroups.com
- Auto named queries and finders are cool.
- Protected empty constructor is somewhat useful.
- I doubt consensus can be found around a standard equals/hashcode implementation, as all implementations are broken in certain fairly common contexts. I'd abandon that idea.

Moandji

Petr Jiricka

unread,
Feb 26, 2010, 7:41:33 AM2/26/10
to project...@googlegroups.com
Some time ago, I suggested Lombok-based annotations to automatically generate finder methods for Java Persistence - see the e-mail below. An initial implementation of this framework is now available here: http://kenai.com/projects/jpa-dynamic-finders

Here is a screencast that explains how it can be used:

In short, there is an annotation called @AutoFinders that is used on a class (typically a DAO). One parameter of the annotation specifies the finder methods to be generated, and another parameter determines the return type (entity type). The argument list for the generated finder methods is automatically inferred from the method name, and the framework generates the entire implementation of the finder methods. 
The library supports simple queries by column name (e.g. findByCustomerId), comparison operators such as <, <=, >, !=, isNull, isNotNull, like, between etc (e.g. findByPriceLowerThan), logical operators And and Or to compose queries for multiple columns (e.g. findByNameAndStreet), or the combination of the above.
 
The library also provides one other way to generate finder methods, which is not based on Lombok. This is based on the feedback from Reinier, who questioned whether Lombok is needed at all to provide this functionality, or whether this can be implemented without Lombok. This other approach is also demonstrated in the screencast, so you can answer for yourself which is better. My opinion is that the Lombok-based approach is superior, because:
- It requires you to write even less code. You only need to provide the finder method name - with the alternative approach you need to specify the entire signature of the method. 
- It does not depend on dependency injection frameworks (such as CDI and its @Inject annotation, or Spring's @Autowire) to locate and instantiate the implementation class.

Either way, in both of these approaches the body of the generated finder method is a very short block of code, that just delegates to a runtime part of the library, which does the real work. This approach helps in debugging the potential problems and makes the library more transparent.
I would be interested to know what you think about these approaches, and whether you find the Lombok-based or the non-Lombok-based approach better/cleaner/more elegant etc. 

I was not sure to what extent the library should take Spring and its development approach into account. My hope is that it can be easily used in a Spring-based environment, though by default, the presence of Spring is not assumed and the library is independent of Spring. While Spring is currently used in the vast majority of enterprise applications, with the new frameworks such as CDI (JSR 299) and the Java EE 6 platform, Spring will not be as ubiquitous as previously. Also, after some research I found that there are already some frameworks which provide dynamic finders capability in a Spring-based environment:

Spring Roo: http://www.springsource.org/roo

So, Spring users already have many options when it comes to dynamically generated finder methods, but for non-Spring usages, I did not find any analogous libraries/frameworks. That said, I would love to hear suggestions about how to make the Dynamic Finders library more applicable and relevant to Spring-based apps, and learn about aspects of the library which are not Spring-friendly.

Speaking of the approaches above, it turns out that Arid POJOs and Hades generate the finders implementation based on a user-provided interface (similarly to the non-Lombok-based approach in my library), so the user needs to specify the full signature of the finder method, which in my mind is a disadvantage. With Spring Roo, on the other hand, the user just specifies the finder method name (not the full signature), which is similar to the Lombok-based approach above. However, the downside is that code generation happens at design time (not build time), so the user has to deal with generated code that needs to be put into VCS and is not hidden from the user. Moreover, the code generated by Spring Roo is in AspectJ - a language that many Java developers are not familiar with.

Finally, here are some other random notes about the Dynamic Finders library and the approach:
- The implementation for Eclipse is not yet available, it only works with javac (plus Ant, Maven, NetBeans, ...). As Lombok is undergoing a major rewrite, after which there will be a unified way to write handlers for javac and Eclipse, this seemed like throwaway work.
- Java Persistence version 2.0 (i.e. EclipseLink 2.0 as the only available implementation of JPA 2 right now) is required, because of the reliance on the new Criteria Query API, which was added in JPA 2.
- I did not implement any support for named queries, as suggested in the original e-mail below. Finder methods seem to be the more developer-friendly way to query the database in JPA, so I assume there will be more interest in those.

Please let me know your feedback and comments on the library, the approach it takes, its usefulness, applicability in various environments etc.

Thanks,
Petr

Begin forwarded message:

Jacek Furmankiewicz

unread,
Feb 26, 2010, 9:18:17 AM2/26/10
to Project Lombok
Petr, let me just say that this is amazing. We are more of a Spring/
Hibernate shop, but we may decided to move to JPA (with Hibernate as
the provider)
just because of enhancements like these.

I have a little suggestion...recently I spent some time with Python
Django and loved their dynamic ORM methods:
http://docs.djangoproject.com/en/dev/topics/db/queries/

for example:

q = Entry.objects.filter(headline__startswith="What")

maybe you could add similar functionality as well where you could add
finders with more finegrained criteria,e.g.

finders={"findByCustomerName_StartsWith","findByCustomerName_LowerCase",})

Also, in many of these finders we have custom security requirements
(e.g. some users may be able to view orders for Customer X and Y, but
others may be able to view orders only for Customer X").

It would be great if we could provide some sort of interceptor
mechanism for auto-generated finders (both pre- and post).

Pre-interceptors could be used for security access, post-interceptors
could be used for additional filtering based on security restrictions,
etc.

It could be done with AspectJ, but I'd rather do simple Java code if
possible instead.

Maybe something like:

finders={"securityCheck;findByCustomerName"})

public boolean securityCheck(String customerName) {
return allowedCustomers.contains(customerName);
}

We would also need finders by multiple fields, e.g.:

finders={"securityCheck;findByCountryCodeAndCustomerName"})

public boolean securityCheck(String countryCode, String customerName)
{
return allowedCountry.contains(countryCode);
}

etc.

Just trying to cover the use cases we have in real life apps, so that
it can be actually useful.

Great work, thank you for your efforts,
Jacek


Petr Jiricka

unread,
Feb 26, 2010, 12:19:30 PM2/26/10
to project...@googlegroups.com
On Feb 26, 2010, at 3:18 PM, Jacek Furmankiewicz wrote:

> Petr, let me just say that this is amazing. We are more of a Spring/
> Hibernate shop, but we may decided to move to JPA (with Hibernate as
> the provider)
> just because of enhancements like these.

Hi Jacek, thanks for the kind words. See more below.

>
> I have a little suggestion...recently I spent some time with Python
> Django and loved their dynamic ORM methods:
> http://docs.djangoproject.com/en/dev/topics/db/queries/

Thanks for the link, I will investigate how this works in Django.

>
> for example:
>
> q = Entry.objects.filter(headline__startswith="What")
>
> maybe you could add similar functionality as well where you could add
> finders with more finegrained criteria,e.g.
>
> finders
> ={"findByCustomerName_StartsWith","findByCustomerName_LowerCase",})
>

It sounds that "startsWith" can be emulated with "like", or not? On
the other hand, lowerCase could be useful.

> Also, in many of these finders we have custom security requirements
> (e.g. some users may be able to view orders for Customer X and Y, but
> others may be able to view orders only for Customer X").
>
> It would be great if we could provide some sort of interceptor
> mechanism for auto-generated finders (both pre- and post).
>
> Pre-interceptors could be used for security access, post-interceptors
> could be used for additional filtering based on security restrictions,
> etc.
>
> It could be done with AspectJ, but I'd rather do simple Java code if
> possible instead.
>
> Maybe something like:
>
> finders={"securityCheck;findByCustomerName"})
>
> public boolean securityCheck(String customerName) {
> return allowedCustomers.contains(customerName);
> }
>
> We would also need finders by multiple fields, e.g.:
>
> finders={"securityCheck;findByCountryCodeAndCustomerName"})
>
> public boolean securityCheck(String countryCode, String customerName)
> {
> return allowedCountry.contains(countryCode);
> }
>
> etc.
>

I agree that having built-in support would be better than having to
use AspectJ - although for this particular case, couldn't it be done
by creating a subclass? Though that's probably not what you are
looking for. Anyway, I guess we could use the bug tracker at kenai.com
to record feature requests like this, so they are not lost in e-mail.

> Just trying to cover the use cases we have in real life apps, so that
> it can be actually useful.

That's exactly what I was looking for - thanks many times!
Petr

>
> Great work, thank you for your efforts,
> Jacek
>
>

Reinier Zwitserloot

unread,
Feb 27, 2010, 9:21:10 AM2/27/10
to Project Lombok
That's _fantastic_, Petr, really shows the power of DSLs. I haven't
worked much with JPA before but this is a fairly convincing argument
to start using it the next time I need persistence.

Roel and I will talk more about where lombok should go to accomodate
@AutoFinders and other good stuff. The main issue remains how to have
lombok plugins. Perhaps Jigsaw will offer something. Clearly a
LOMBOK_HOME kind of deal is not a good idea; each project is different
and it would be classpath hell all over again if plugins are applied
to all projects indiscriminately (something that _is_ the case in
today's lombok, unfortunately). If jigsaw offers a central repository
for java modules then all lombok really needs to do is read a list of
module names per project (module) somewhere and apply them all to any
source files in that project (module). There's a minor issue of
ordering (in which order are the processors run?) but that is solvable
and probably not that important (e.g. AutoFinders and something like
Getter just don't get in each other's way, if you have both of them in
one class it doesn't matter in which order the annotations are
processed).

I can also see the benefits of lombok automatically picking up certain
(probably annotated :P) source files in a project itself, compile
them, and run them against other source files in that project. A sort
of on-the-fly macro ability for java, built around a designed-for-
public-consumption.

We're still working on the AST, which is coming along nicely so far.

> > Groups group forhttp://projectlombok.org/

Petr Jiricka

unread,
Mar 1, 2010, 4:17:44 AM3/1/10
to project...@googlegroups.com
On Feb 27, 2010, at 3:21 PM, Reinier Zwitserloot wrote:

> That's _fantastic_, Petr, really shows the power of DSLs. I haven't
> worked much with JPA before but this is a fairly convincing argument
> to start using it the next time I need persistence.

As an aside, I think Java Persistence is now a mature and usable
framework, and there is no reason not to use it (if O-R mapping in
general is suitable for the project). JPA 1.0 had many limitations
compared to using straight Hibernate and the Hibernate-specific APIs,
but with JPA 2.0, a lot more experience gathered by the users of
Hibernate, TopLink/EclipseLink, Kodo and other frameworks has been
folded into the standard, so JPA 2.0 does not lack compared to using
framework-specific APIs. It can also be used independently of the rest
of the Java EE 6 stack, e.g. you can just drop it into Tomcat, and
Spring 3 interoperates with JPA 2.0.

>
> Roel and I will talk more about where lombok should go to accomodate
> @AutoFinders and other good stuff. The main issue remains how to have
> lombok plugins.

One other particular obstacle I came across was the IDE support. While
the built-in Lombok annotations work well with NetBeans 6.8, to make
the @AutoFinders annotation work with NetBeans, I had to copy the
classes from the dynamic finders library and the javax.persistence.*
API classes into lombok.jar (the copy of lombok.jar that was installed
into the IDE). Hopefully, with the built-in support for annotation
processors in NetBeans 6.9, things will "just work" by adding the
libraries to your project's classpath, and no installation step will
be necessary.

> Perhaps Jigsaw will offer something. Clearly a
> LOMBOK_HOME kind of deal is not a good idea; each project is different
> and it would be classpath hell all over again if plugins are applied
> to all projects indiscriminately (something that _is_ the case in
> today's lombok, unfortunately). If jigsaw offers a central repository
> for java modules then all lombok really needs to do is read a list of
> module names per project (module) somewhere and apply them all to any
> source files in that project (module). There's a minor issue of
> ordering (in which order are the processors run?) but that is solvable
> and probably not that important (e.g. AutoFinders and something like
> Getter just don't get in each other's way, if you have both of them in
> one class it doesn't matter in which order the annotations are
> processed).
>
> I can also see the benefits of lombok automatically picking up certain
> (probably annotated :P) source files in a project itself, compile
> them, and run them against other source files in that project. A sort
> of on-the-fly macro ability for java, built around a designed-for-
> public-consumption.

I will be watching how Lombok will addess this area, and then adjust
the dynamic finders library to whatever approach Lombok takes.

>
> We're still working on the AST, which is coming along nicely so far.
>

Great to hear, I am eager to adjust the library to the new AST as
well, whenever it is ready.

Petr

> Groups group for http://projectlombok.org/

Maaartin

unread,
Apr 17, 2010, 10:01:17 AM4/17/10
to Project Lombok
Aren't annotations themself the very source of problems? I mean, if
there're some code lines I need at many places, I write a method for
it. If there're some annotations I need at many places, I'm lost.

In the example above

@Id @Column(name = "F_SUBSCRIBER_PK")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="S_SUBSCRIBER")
@SequenceGenerator(name="S_SUBSCRIBER",sequenceName="S_SUBSCRIBER")
private Long primaryKey;

there's hardly any information there and as already said, it all could
be replaced by something like

@MyGeneratedValue(strategy=GenerationType.SEQUENCE,generator="S_SUBSCRIBER")
private Long primaryKey;

If there was a way how to put annotations on classes, even beginners
could program the transformation from @MyGeneratedValue to the above
pack of annotations. Of course, there's no such thing like
java.lang.reflect.Method.setAnnotation, and this can't be done at
runtime, but couldn't lombok help here?

In order to make my idea clear I describe, what I'd do (if I could) on
source code level: Before compilation scan for annotations, pass them
together with the context to user supplied method replaceAnnotations,
and copy the result into the source code given to the compiler. The
user supplied method replaceAnnotations could look like
public Set<Annotation> replaceAnnotations(Set<Annotation> annotations,
String className, String methodName);

Having something like this would be much better than something as
special as lombok.jpa. It could be used for many frameworks and it
would be very powerful and quite easy to use. I'm quite sure, there'd
be people writing such annotations replacers for all the common
frameworks including JPA.

My big question is: Is something like this possible?


PS: The above annotation example could be simplified further to
something like

@MyPrimaryKey
private Long primaryKey;

by putting the specification of the strategy and of the generator name
into a single place (outside of the entities; the generator name would
be build using the entity name). I think, this is not general enough
to be put into lombok, but it should not be. Lombok should only
provide a way for letting users do it.


PPS: Others may prefer to annotate the class with @MyEntity and let
the field "primaryKey" be generated automatically. This is something
in the sense of what lombok is doing, isn't it?


PPPS: Recently, I've had problems posting in this group, I apologize
for possible multiple postings.

Reinier Zwitserloot

unread,
Apr 17, 2010, 5:18:13 PM4/17/10
to Project Lombok
Lombok could most certainly add a bunch of annotations onto a method
as the transformative step triggered by a different annotation on that
method. Though, at the moment, if you need resolved type info from the
method you're out of luck, that's something we're working on. (i.e. if
you need to know the complete package of the return type of the
annotation method or something).
> Groups group forhttp://projectlombok.org/

Maaartin

unread,
Apr 17, 2010, 7:06:09 PM4/17/10
to Project Lombok, graj...@seznam.cz
On Apr 17, 11:18 pm, Reinier Zwitserloot <reini...@gmail.com> wrote:
> Lombok could most certainly add a bunch of annotations onto a method
> as the transformative step triggered by a different annotation on that
> method. Though, at the moment, if you need resolved type info from the
> method you're out of luck, that's something we're working on. (i.e. if
> you need to know the complete package of the return type of the
> annotation method or something).

And don't you think this is a good idea? I know about the resolution
problem, but you'll solve it eventually, since you need it for many
thinks anyway.

Of course, the idea requires some tuning, for example working with
annotations (especially creating them) is quite a pain, so letting
users to work with them directly may be a bad idea. In order to show
how flexible it is, I wrote a simple example which generates all the
JPA boilerplate mentioned above - provided Lombok does all the hard
work:
http://dl.dropbox.com/u/4971686/replaceAnnotations.txt
(I don't think copying the code here would be of any use since the
line breaking "feature" makes it completely unreadable.)

Reinier Zwitserloot

unread,
Apr 17, 2010, 7:58:44 PM4/17/10
to Project Lombok
The API will be a little different but you got the gist of it. We'll
look into it.

On Apr 18, 1:06 am, Maaartin <grajc...@seznam.cz> wrote:
> On Apr 17, 11:18 pm, Reinier Zwitserloot <reini...@gmail.com> wrote:
>
> > Lombok could most certainly add a bunch of annotations onto a method
> > as the transformative step triggered by a different annotation on that
> > method. Though, at the moment, if you need resolved type info from the
> > method you're out of luck, that's something we're working on. (i.e. if
> > you need to know the complete package of the return type of the
> > annotation method or something).
>
> And don't you think this is a good idea? I know about the resolution
> problem, but you'll solve it eventually, since you need it for many
> thinks anyway.
>
> Of course, the idea requires some tuning, for example working with
> annotations (especially creating them) is quite a pain, so letting
> users to work with them directly may be a bad idea. In order to show
> how flexible it is, I wrote a simple example which generates all the
> JPA boilerplate mentioned above - provided Lombok does all the hard
> work:http://dl.dropbox.com/u/4971686/replaceAnnotations.txt
> (I don't think copying the code here would be of any use since the
> line breaking "feature" makes it completely unreadable.)
>
> --
> You received this message because you are subscribed to the Google
> Groups group forhttp://projectlombok.org/
Reply all
Reply to author
Forward
0 new messages