18

In C# you can enclose a lambda expression in an expression tree object and then possibly parse it. I was wondering if this is also possible in Java?

What I'm looking for is doing something like this:

BooksRepository.getAll()
.where(b -> b.getIban() == "SomeIban")
.and(b -> b.getAuthor() == "SomeAuthor"); //etc.

And then the BooksRepository should somehow translate that query to the following RESTful API request based on the predicates specified as lambdas:

GET http://mylibrary.com/books?Iban=SomeIban&Author=SomeAuthor

and then return the result to the client. Any idea if this is even possible in Java?

17
  • 5
    That's a noble goal, but lambdas will not help you with it at all. Nothing comparable exists in Java. Sep 23, 2014 at 7:47
  • 1
    What’s the advantage of writing .where(b -> b.getIban() == "SomeIban") instead of WHERE IBAN = 'SomeIban' (as part of an SQL statement)? It would be powerful if it could translate arbitrary Java code but the corresponding C# feature is limited to simple expressions so it stops right where it could start to become useful…
    – Holger
    Sep 23, 2014 at 8:03
  • 5
    @Holger The advantage is avoiding opaque, non-syntax-checked strings. But I would prefer jOOQ any day to this, because with that approach you can have reusable parts of SQL represented in Java objects. On the other hand, that approach is specific to SQL and is not what OP is asking about here. Sep 23, 2014 at 8:18
  • 3
    @Holger refactoring, compilation time checks, auto-completion and abstraction of the underlying query implementation.
    – Eyad
    Sep 23, 2014 at 8:23
  • 3
    @Holger Agreed, especially your point in the first sentence. The lambda can be anything and only the runtime will hit you with an error. Even worse, it seems that the runtime will "seamlessly" revert to in-JVM processing. Y-U-C-K. Sep 23, 2014 at 8:28

4 Answers 4

10

Yes, it's possible. I made a library that does exactly that: JaQue

2
  • 1
    This is remarkable and I'm really sad to see that this project has gotten so little attention and appears to be abandoned. LINQ is one thing, but I think Expressions are one of the most powerful features of C# and .NET and the ability to do type-safe, fluent configuration is incredibly powerful and expressive.
    – Avi Cherry
    Apr 28, 2017 at 0:42
  • @AviCherry: thanks for your comment. If you think the project is important, you may vote here and in some linked questions on the right. Hopefully it will make it more visible. BTW, it's not dead. I simply don't have any open item on it ;-). After all, it's a library with a well defined API. The API is implemented, tests written, several bugs reported and fixed. Apr 29, 2017 at 18:15
9

I'm the author of Jinq. The automatic conversions of lambdas into expression trees that can be read at runtime is a C# only feature. That feature doesn't really have any general-purpose use for normal programmers. It's basically only useful for implementing LINQ, so language designers haven't been keen on adding that feature to Java or other languages. There has been talk of adding some sort of compiler plugin framework for Java that would allow you to add the expression tree feature to Java yourself, but I'm not too familiar with progress on that project.

Jinq contains a bytecode analysis framework that can build simple expression trees from the bytecode of a lambda at runtime. It is based on symbolic execution and ASM. It can be used to convert lambdas into expression trees, just like C#, but it's pretty heavy weight procedure with a lot of hoops to jump through, so it might be overkill for what you want to do. You'd be swatting a fly with a hammer, essentially.

There are languages other than Java that run on the JVM that have better support for the metaprogramming that you want to do. So you might also want to consider looking at Groovy or Scala for that.

5
  • Hi Dr. Ming. You are absolutely right in saying that if this was my only requirement then I would be "swatting a fly with a hammer", but it is not. Actually, the example I gave in the question was just a simple use case of many other things that I have in mind as we are moving towards java 8 from two way object mapping (ala automapper), validation rules (ala fluent validation.net), to workflow DSLs in addition to abstract RESTful queries.
    – Eyad
    Sep 25, 2014 at 5:58
  • Oh, and BTW, I've read your article about symbolic execution and have been (trying) to understand of the analysis package of jinq (very impressive work by the way), but that was quite challenging for me being new to the whole java world. Do you happen to have any sort of documentation of the analysis package of Jinq?
    – Eyad
    Sep 25, 2014 at 6:00
  • If you're only doing simple queries though, it'll be a lot easier just to design a simpler API that doesn't require lambdas as input. If you have a specific question about Jinq, it's probably easier just to e-mail me directly about it. There is no documentation for the analysis package. You can see how it is used by looking at the jinq-jpa/main/org/jinq/jpa/transform/LambdaInfo.java file. Sep 26, 2014 at 15:55
  • C# does have some great features. Microsoft's design philosophy is to add new features to C# quickly without worrying too much about breaking old things. Java evolves slowly and waits for general consensus before doing so. Experience has shown that Linq expressions are useful for building query systems, as your system is. But are they useful for other things? Why are they limited to expressions? Why not a more powerful metaprogramming feature that also works with statements? This lack of consensus is why Java does not have this feature yet. Java offers annotations as a kludgy alternative. Oct 21, 2014 at 15:45
  • 3
    Dude, you should calm down a bit. I don't see why you're getting so worked up over something as esoteric as programming language design. I sometimes code in C# myself. When I said C# "moves fast and break things", I meant that as a compliment, but I couldn't elaborate due to character limitations in comments. It's the Silicon Valley way. People regularly praise Apple for deprecating old APIs. The natural result of moving fast is that some stuff breaks. Java evolves slowly, but sometimes that's too slow. C# uses a different set of trade-offs than Java. No language is perfect. Chill out, man. Oct 23, 2014 at 18:51
4

Something like Jinq?

database.customerStream().where(customer -> customer.getName().equals("Alice"));
1
  • Exactly! See comments under the main question.
    – Eyad
    Sep 24, 2014 at 17:26
2

I explain my approach here http://benjiweber.co.uk/blog/2013/12/28/typesafe-database-interaction-with-java-8/

Basically, replay the lambda against a fake object that records the interactions at runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.