1

I'm using an Java Servlet (with embedded Jetty, no Spring, no frameworks) and I'm adding asynchronous processing and caching to it. The exact implementation is irrelevant to this question and it's not very Java-specific. My problem is the overall code structure, which before the additions looks like this pseudocode

void service1() {
    addFixedHeaders();

    try {
        service2();
    } catch (MyException e) {
       ...
    } catch (AnotherException e) {
      ...
    }

    addMoreHeadersUnlessAlreadySet();
    writeResponse();
}

void service2() {
   addCorsIfNeeded();
   if (needsForwarding())  {
       doForwarding();
   } else {
       service3();
   }
}

void service3() {
    if (hasEtag() && isStillValid()) {
       serveMotModified();
    } else {
        service4();
    }
}

Basically, it's a sequence of calls service1 -> service2 -> service3 -> ... with some pre- and postprocessing (kind of inline FilterChain), where some calls are conditional. I used to be satisfied with it.

However, adding caching (I mean serving 200 response from server cache rather than serving 304, which fits nicely) requires changes in multiple methods. This gets complicated by caching static and dynamic content differently and using the same cache also for avoiding compression. This makes the code rather ugly, while I'd prefer some functional style like

return cache.getOrCompute(key, key -> someComputation(key))

Independently, as an experiment, I've also added asynchronous processing (which is needed for some requests only). This required a major rewrite and lead to something exceptionally awful (and would get even worse when caching was added). I'm thinking about something like this chain

void service1() {
    process1();
    if (isSimple1()) {
       shortcut1();
    } else if (wantsAsync1()) {
        callAsync(service2); 
    } else {
        service2(); 
    }
}

when most methods will have only some parts. What I dislike here, is that there's no possibility to handle exceptions in a single place (like my in first service1. It also forces me to move the postprocessing to some service99 which doesn't make obvious, that it always happens.

I wonder, if there's a suitable pattern, something like promise chaining or whatever (I'm not looking for a library though I don't insist on reinventing the wheel). Something simple, yet flexible, so that further additions fits nicely in the pattern.

  • Q1: Why don't you handle all exceptions in a separate servlet? Q2: Why don't you implement caching as an actual filter? – scriptin Jul 7 '17 at 18:03
  • @scriptin Can you elaborate? Q1: How would a separate servlet know what exception occured? When and how would I call it? Q2: Should the filter read the cached value from the response output stream? How would it avoid extracting data from the request the same way the servlet does? – maaartinus Jul 8 '17 at 11:27
  • Q1: See this example, Q2: It depends on what you want to cache and on which level (request-response level, services level, etc.); see javaee-cache-filter for some examples. It would not avoid extracting data, but it would separate the concerns. The main issue I see in your code is that you put everything in one place, which creates a big ball of mud – scriptin Jul 8 '17 at 13:07
  • @scriptin Q1: Thank you. It doesn't really fit, but was helpful. Q2: In the end, I want to cache everything as much as possible: 1. 304 NOT MODIFIED, 2. static resources, 3. dynamic resources once I get the invalidation working, 4. compression (when I get a cache miss, compute the etag (which is globally unique) and find out that there's already matching compressed data). +++ "big ball of mud" - that's why I'm asking here. I've improved the code in the meantime a lot (it's 34 lines calling 10 methods in a linear fashion and writing some stats). – maaartinus Jul 9 '17 at 15:32
  • 1
    Since you have 4 points in your caching list, I'd suggest implementing them as 4 filters. Instead of fighting Servlet architecture it's better to follow it. It has its flaws, but since you decided to not use any frameworks, it's the next best thing. – scriptin Jul 9 '17 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.