9

I am trying to migrate to java 8 and have a number of methods in my dao classes which do the following

@Override
@SuppressWarnings("unchecked")
public List<Group> getGroups()
{
    Session session = sessionFactory.openSession();
    List<Group> allGroups = (List<Group>)session.createQuery("from Group").list();
    session.close();
    return allGroups;
}

Here the same boiler plate sessionFactory.open and session.close is repeated for all methods.

Is it possible in Java 8 to have a method which does the open and close and takes a function which is the rest of my code and execute it inbetween?

If so - what is the name of this process , or can anyone provide some help on how this might be achieved

Holger
  • 285,553
  • 42
  • 434
  • 765
Biscuit128
  • 5,218
  • 22
  • 89
  • 149
  • 1
    I think you're talking about aspects (AOP) here. :) – Konstantin Yovkov Jun 15 '15 at 09:40
  • 2
    This is not methods which you'll parse as arguments but instances of functional interfaces. Provided you create your own functional interface and ensure that all your methods match its signature then yes, you can do it. – fge Jun 15 '15 at 09:40

1 Answers1

14

Since you want to express code which works on a Session instance (so you can abstract the creation and cleanup of it) and might return an arbitrary result, a Function<Session,T> would be the right type for encapsulating such code:

public <T> T doWithSession(Function<Session,T> f) {
    Session session = sessionFactory.openSession();
    try {
        return f.apply(session);
    }
    finally {
        session.close();
    }
}

then you can use it like:

@Override
@SuppressWarnings("unchecked")
public List<Group> getGroups()
{
    return doWithSession(session -> (List<Group>)session.createQuery("from Group").list());
}

This isn’t a special Java 8 technique. You can do the same in earlier Java version, see also What is the “execute around” idiom (Thanks to gustafc for the link). What makes it easier is that Java 8 provides you with an existing Function interface and that you can implement that interface using a lambda expression instead of having to resort to anonymous inner classes or such alike.

If your desired operation consists of a single method invocation and doesn’t require a type cast, you can implement it as a method reference like doWithSession(Session::methodName), see Method References in the tutorial

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
  • 2
    Related: [What is the "execute around" idiom?](http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom) – gustafc Jun 15 '15 at 09:51