0

I had asked a question earlier regarding ExecutorService and Apache Velocity initialization. To give a quick recap -- I have a Java EE frontend which accepts user requests and then for each of these requests, uses ExecutorService(SingleThreadedExecutor set as a daemon) to kick off a lengthy workflow.This workflow is contained in a library and works well and as expected when run in a standalone mode through eclipse. When called from the website(servlet) I observed that the workflows were consistently getting hung at the point where the Velocity Engine was being initialized (Velocity.init() or ve.init()). Hence my aforementioned question.

When none of the answers/suggestions worked i inferred that this was something to do with the way Velocity started up and decided to shift to FreeMarker. Now i see that the workflow is getting hung in the exact same place for the FreeMarker implementation as well. This 'place' is the mail-building part which evaluates a template against a coupel of passed data objects and returns the mail string.The class that calls the Freemark'ing class and the FreeMark class are as follows --

   public class mailBuilder {

    private static final Logger log = Logger.getLogger( mailBuilder.class );    
    static String a;
    static String b;

    public mailBuilder(CustomDataStructure input)
    {
        a = input.getA();
        b = input.getB(); 
    }
    public static String returnMailstring() throws Exception
    {
        log.info("Gathering elements to construct email.");
        String mailText=null;
        Map context = new HashMap();
        context.put("a",a);
        context.put("b",b);
        log.info("Calling Freemarker");
        mailText=FreeMarkIT.ReturnReportString(context);
        log.info("Freeemarker returned string");

        return mailText;
    }
}

FreeMarkIT class is as follows --

    public class FreeMarkIT {
        private static final Logger log = Logger.getLogger( FreeMarkIT.class );
        private static Configuration config;
        private static Template template;

        public static String ReturnReportString(Map model) throws IOException, TemplateException
        {
            StringWriter sw = new StringWriter();
            try 
            {
               log.info("Going to get the template");
               config= new Configuration();
               log.info("Now really");
               template=config.getTemplate("src/resource/email_template.vm");
               log.info("Done initializing template");
               template.process(model, sw);
               sw.flush();
            }
            catch(Exception e)
            {
                System.out.println(e.getMessage());
            }

            return sw.getBuffer().toString();
        }
    }

Now, from my logging it looks like the worker thread hangs at the line config=new Configuration()

Again, this works as expected in a standalone mode when run from eclipse but however hangs when called from the servlet using ExecutorService.

Im beginning to think/realize that this may have nothing to do with either of Velocity or FreeMarker and have something to do with ExecutorService. Any advice or suggestion would be of immense help.

Thanks

Community
  • 1
  • 1
ping
  • 1,229
  • 3
  • 21
  • 41
  • Your code is not valid Java code. What's sure is that it's very far from being thread-safe. Show us the real code, because all the corrections we might do on fake code won't be useful. And please respect Java naming conventions: your code is hard to read. – JB Nizet Jan 01 '12 at 13:52
  • I apologize. I have fixed the code now. – ping Jan 01 '12 at 14:04

1 Answers1

3

your code is not thread-safe since you are sharing config and template across all thread instances (and continuously re-setting them). the easiest way to make it thread safe would be to make config and template local variables in the method instead of static members. as @JBNizet pointed out in the comments, you have a similar problem in mailBuilder with a and b. you might want to first check out some tutorials on object oriented programming fundamentals and then circle back to this issue (hint, in general you should avoid static member variables except for constants).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • 3
    +1. The variables a and b, and the returnMailstring method in mailBuilder should also not be static. – JB Nizet Jan 01 '12 at 14:08
  • Ah, but wont there be just 1 thread accessing them because of the fact that the ExecutorService is a SingleThreadedExecutor ? Im trying your suggestion right now. – ping Jan 01 '12 at 14:09
  • 2
    We haven't seen how you're using your executor. You have at least two threads: the request-handling thread, and the worker thread. Your code is not only non-thread-safe, but badly designed. Start by fixing the design issues, and at least see if it fixes the problem. – JB Nizet Jan 01 '12 at 14:12
  • I have tried the above and can say that the problem remains.My executor is based on nos's reply in the following thread --http://stackoverflow.com/questions/4907502/running-a-background-java-program-in-tomcat – ping Jan 01 '12 at 14:43
  • @ping - post your updated code and a thread dump showing where your code is stuck – jtahlborn Jan 01 '12 at 15:46
  • Just as a side note, FreeMarker's `Configuration` and `Template` objects are thread-safe as far as you don't explicitly call their mutators methods, and you don't. (The code still doesn't make sense, because the `Configuration` instance is not reused, yet it's stored in a field.) But, the data-model (context) that you access from a FreeMarker template is not synchronized by FreeMarker on any way. So the data-model has to be thread-safe, if you share it among multiple threads that run FreeMarker. – ddekany Jan 02 '12 at 00:09
  • @jtahlborn It after all was because of my classes not being thread safe. Making them so solved the issue. Im going ahead and accepting your answer. I now have a job of understanding the need for thread safety when using a SingleThreadedExecutor. Thanks for all the help. – ping Jan 02 '12 at 07:42