Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

Strongly-typed Fluent API? #3

Open
mstine opened this issue Jan 12, 2013 · 6 comments
Open

Strongly-typed Fluent API? #3

mstine opened this issue Jan 12, 2013 · 6 comments
Milestone

Comments

@mstine
Copy link

mstine commented Jan 12, 2013

Hi! I'm currently working on a new talk for the 2013 No Fluff Just Stuff tour entitled "Programming with Immutability." I was very pleased to find JIRM, as one of the primary questions that I get when I discuss immutability on the tour is "How do I do Hibernate with immutable classes?"

I really like your fluent API. I'm wondering what it would take to make it strongly-typed?

For example...the following code:

customerService.getDao().update()
   .set("name", "John Doe")
   .where().property("id", 1L)
   .execute();

might become:

customerService.getDao().update()
   .set(name(), "John Doe")
   .where().property(id(), 1L)
   .execute();

or something similar. Since we know the type of the class that the Dao is for, it seems like this should be possible. I'd be interested in helping with this if you could point me to the right place to start looking at it.

Thanks again!
-Matt

@lukaseder
Copy link

(Disclaimer: I'm not the repo owner, I'm just following this project)
I feel that Lambdaj might have a good answer to this problem:
http://code.google.com/p/lambdaj/

Lambdaj allows for expressing property proxies like this:

// Bean proxy 
on(Person.class);

// Property proxy
on(Person.class).getAge()

More details:
http://lambdaj.googlecode.com/svn/trunk/html/apidocs/ch/lambdaj/Lambda.html#on(java.lang.Class)

Translated to your example, this could become something along these lines:

JirmDao<CustomerBean> dao = customerService.getDao();
dao.update()
   .set(dao.bean().name(), "John Doe")
   .where().property(dao.bean().id(), 1L)
   .execute();

Where dao.bean() would wrap the bean proxy, and dao.bean().name() would be a property proxy. If this works out, I might start stealing more ideas from JIRM ;-)

@mstine
Copy link
Author

mstine commented Jan 12, 2013

Yes! I very much has Lambdaj in mind when I wrote this...just didn't get the syntax quite right.

I may try this in a local branch and see how it goes.

Sent from my iPhone

On Jan 12, 2013, at 4:32 PM, Lukas Eder [email protected] wrote:

(Disclaimer: I'm not the repo owner, I'm just following this project)
I feel that Lambdaj might have a good answer to this problem:
http://code.google.com/p/lambdaj/

Lambdaj allows for expressing property proxies like this:

// Bean proxy
on(Person.class);

// Property proxy
on(Person.class).getAge()
More details:
http://lambdaj.googlecode.com/svn/trunk/html/apidocs/ch/lambdaj/Lambda.html#on(java.lang.Class)

Translated to your example, this could become something along these lines:

JirmDao dao = customerService.getDao();
dao.update()
.set(dao.bean().name(), "John Doe")
.where().property(dao.bean().id(), 1L)
.execute();
Where dao.bean() would wrap the bean proxy, and dao.bean().name() would be a property proxy. If this works out, I might start stealing more ideas from JIRM ;-)


Reply to this email directly or view it on GitHub.

@agentgt
Copy link
Owner

agentgt commented Jan 13, 2013

I thought about doing this Matt but some of the reasons I did not are:

  • Added Complexity
  • Hard to implement with out adding some sort of state machine (thread safety)
  • Spirit of API to favor normal SQL (ie sql templates)

You should definitely checkout @lukaseder (Lukas Eder) JOOQ library (he humbly omitted that in his previous comment :) ) as it supports querying into immutable POJOs with a fluent API. JOOQ is more database table focus and I guess mine is more immutable object focused. Actually sort of funny thing is we have sister projects in both database (JOOQ, JIRM) and (X)HTML generation (JOOX, JATL). I will say his are generally superior and I really should have started reading his blog lot sooner to avoid duplication :) .

That being said I think I can see how I can do this as I have seen it done with things like Mockito and jMock (both use state machines and dynamic proxies IIRC).

@agentgt
Copy link
Owner

agentgt commented Jan 13, 2013

Matt (@mstine),
I was thinking about this last night again and remembered why I didn't explore this more.
I think the real issue is that Java Bean's or I should say Java Properties are "made up" citizens in the Java language. (Lukas just blogged about this).

The problem is that is impossible in Java to statically refer to a property. However there are code generators that will take some sort of description and generate an immutable object with static references to all its properties (ie meta-data). One example is Protobuf.

So what I'm proposing instead of the dynamic proxy approach which requires tricky state management and object bytecode generation, and is potentially slow, is that we could just generate immutable objects with their metadata (field names and types as static constants) with a code generator. The jOOQ project code generates based on SQL tables. Perhaps JIRM should approach it from the reverse: Generate based on Immutable Struct definitions (ala protobuf).

Some people see code generation as evil but I don't think its so bad as long as its seamlessly integrated into the toolchain. JSR 269 is one option to explore (see genftw). Another option is to explore an Eclipse Code generator (which is infact what I do right now with a custom version of bpep), or come up with another description language like protobuf.

Finally (and sorry for the lack of brevity but I know your looking for content for NFJS) you might want to check out some hacks I did to make Spring MVC databinding work with immutable objects on stackoverflow. With the Spring hack and JIRM I have almost eliminated regular getter/setter Java beans in my newer projects.

@mstine
Copy link
Author

mstine commented Jan 15, 2013

Thanks folks for all of the feedback/ideas.

This is definitely not a deal breaker for me. I'll certainly be highlighting JIRM in my talk. I was able to get a basic "Hello World" app bootstrapped fairly easily. The strong-typing would be a nice addition, as I feel like it fits in well with the overall spirit of functional programming. While my talk isn't strictly about FP, but rather immutability, I will be mentioning quite a few FP concepts during the discussion.

I'd love to continue thinking/collaborating on this issue. As soon as I get a chance to dig into the code more deeply, I'll consider your points a little more closely.

One quick note: I did notice that when I configured an embedded DB using the Spring JDBC XML namespace, the HSQL metadata seemed to always come back upcased (i.e. "ID" instead of "id")...because of this, I was forced to annotate all of my fields with @Column('COLUMN_NAME') for JIRM to work. Is this an artifact of how JIRM works? Or HSQL? Thanks!

@agentgt
Copy link
Owner

agentgt commented Jan 24, 2013

I will be adding HSQL as to the testing suite very soon so I'll see if I see what your talking about.
Right now we only test Postgresql and Mysql.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants