1

I am trying to refactor the below code

class FileDownloadResource{ @Inject private FileDownload fileDownload; @Path(/abc) public Response downloadFileABC(){ try{ fileDownload.downloadABC(); }catch(IOException e){ } //Some code here that is common to the second method as well } @Path(/xyz) public Response downloadFileXYZ(){ try{ fileDownload.downloadXYZ(); }catch(IOException e){ //handle exception } //Some code here that is common to the first method as well } } 

The class is a JAX-RS rest resource. As you can see in the above code, everything except what is in the try block is the same for two method. Can we use any of the new JDK 8 features to pass fileDownload.downloadABC() as an argument to a private method ?

Basically, I am looking for some way to pass a function as an argument and let the other part of the code be same.

2
  • 2
    Even the code in the try-block is the same. Commented Dec 16, 2015 at 5:28
  • 2
    Yup, and my answer assumed that. Tagir's answer is similar to mine, though he uses perhaps better names for the functional interface, while I show both the ABC and XYZ versions of using it. Commented Dec 16, 2015 at 5:44

2 Answers 2

4

Sure you can. You need either to use existing functional interface or create the new one. As you expect checked IOException, it's better to create the new one (you could also use Callable<Void>, but it's less convenient):

@FunctionalInterface interface IORunnable { void run() throws IOException; } 

Now you can create generic request handler private method:

public Response handleRequest(IORunnable r){ try { r.run(); } catch(IOException e){ // handle exception } //Common code follows } 

And use it like this:

@Path("/abc") public Response downloadFileABC(){ return handleRequest(fileDownload::downloadABC); } 

Or with lambda:

@Path("/abc") public Response downloadFileABC(){ return handleRequest(() -> fileDownload.downloadABC()); } 
Sign up to request clarification or add additional context in comments.

Comments

3

You can do this, as long as the downloadABC() and downloadXYZ() methods have the same parameters and return value as the download() method of the Download interface.

Name of interface and interface method can be anything you choose.

@FunctionalInterface interface DownloadMethod { public void doDownload() throws IOException; } class FileDownload { public void downloadABC() throws IOException {} public void downloadXYZ() throws IOException {} } class FileDownloadResource{ @Inject private FileDownload fileDownload; @Path("/abc") public Response downloadFileABC(){ return download(fileDownload::downloadABC); } @Path("/xyz") public Response downloadFileXYZ() { return download(fileDownload::downloadXYZ); } private Response download(DownloadMethod method){ try{ method.doDownload(); }catch(IOException e){ //handle exception } //Some code here that is common to both methods } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.