For those interested, Java 8 actually intends to allow for "optional
returns" from Lambda expressions, i.e. there may be two overloaded versions
of a method, one expecting a Lambda expression with a return and one
without.
So the previous example could actually be written like this:
Foo foo = inTransaction( (session, tx) -> {
Foo f = new Foo();
em.persist( f );
return f;
} );
inTransaction( (session, tx) -> {
Foo f = em.find( Foo.class, foo.getId() );
...
} );
So the first invocation would make use of TransactionBoundaryWithResult and
the second would use TransactionBoundary with the following definitions:
public void inTransaction(TransactionBoundary transactionBoundary) {
...}
public <T> T inTransaction(TransactionBoundaryWithResult<T>
transactionBoundary) {
and
@FunctionalInterface
public interface TransactionBoundary {
void execute(Session session, Transaction transaction);
}
@FunctionalInterface
public interface TransactionBoundaryWithResult<T> {
T execute(Session session, Transaction transaction);
}
Unfortunately though, JDK 8u5 and the Eclipse compiler can't distinguish
the two inTransaction() methods and falsely report an ambiguity error at
the call-site. It works as of 8u20.
--Gunnar
2014-05-16 10:25 GMT+02:00 Gunnar Morling <gunnar(a)hibernate.org>:
I had envisioned inTransactionWithResult() for that purpose. This
returns
a value which can be used in the next lambda expression:
Foo foo = inTransactionWithResult( (session, tx) -> {
Foo f = new Foo();
em.persist( f );
} );
inTransaction( (session, tx) -> {
Foo f = em.find( Foo.class, foo.getId() );
...
} );
But admittedly it doesn't work that nicely when more then one value needs
to be passed between lambdas. Also there is naming conflict between the
variable within the lambda expression and the variable holding the result.
One would naturally like to use the same name - as it is the same thing -
but that's not possible.
I didn't pursue the idea any further since then.
--Gunnar
2014-05-16 9:51 GMT+02:00 Emmanuel Bernard <emmanuel(a)hibernate.org>:
These kind of tests are actually not in isolations between lambdas. You
> often want to pass an id or value between blocks to be reused. I don't
> think lambdas are porous enough for that. That would be surprising.
>
> Emmanuel
>
> On Fri 2014-04-25 10:41, Gunnar Morling wrote:
> > Hey,
> >
> > I've played around a bit with the idea of using Java 8 lambdas to make
> > tests easier to write and read. We have many tests which open a session
> and
> > TX, do some stuff, commit, open a new TX (and/or session), do some
> > assertions and so on:
> >
> > Session session = openSession();
> > Transaction transaction = session.beginTransaction();
> >
> > // heavy testing action...
> > transaction.commit();
> > session.clear();
> >
> > transaction = session.beginTransaction();
> >
> > // load, assert...
> > transaction.commit();
> > session.clear();
> >
> > The same could look like this using Java 8 lambdas:
> >
> > Foo foo = inTransactionWithResult( (session, tx) -> {
> > // heavy testing action...
> > } );
> >
> > inTransaction( (session, tx) -> {
> > // load, assert...
> > } );
> >
> > Extracting the session/TX handling removes quite some clutter and
> focuses
> > more on the actual testing logic. It also avoids problems due to
> dangling
> > transactions e.g. in case of assertion failures as the TX handling is
> done
> > in a finally block in inTransaction().
> >
> > At this point I've just done a quick POC and would be interested in
> > feedback whether you think that's worth pursuing or not. Note that
> > different language levels can be used for test and main code, so we
> could
> > make use of lambdas in tests while ensuring Java 6 compatibility for the
> > delivered artifacts.
> >
> > --Gunnar
> > _______________________________________________
> > hibernate-dev mailing list
> > hibernate-dev(a)lists.jboss.org
> >
https://lists.jboss.org/mailman/listinfo/hibernate-dev
>