title: How can i make a camel route thread safe?
body: <p>I have a camel route which consume task from apache activeMQ.
  Everything works fine when there is only one consumer for ActiveMQ.</p>
  
  <p>But when the consumers gets increased to two (or more), the application behave in an inappropriate manner.</p>
  
  <p>Here is my route:</p>
  
  <pre><code>&lt;routeContext id="myRoute"  xmlns="http://camel.apache.org/schema/spring"&gt;
      &lt;route errorHandlerRef="myErrorHandler" id="myErrorRoute"&gt;
          &lt;from uri="activemq:queue:{{my.queue}}" /&gt;
          &lt;log loggingLevel="DEBUG" message="Message received from my queue : ${body}"&gt;&lt;/log&gt;
          &lt;multicast&gt;
              &lt;pipeline&gt;
                  &lt;log loggingLevel="DEBUG" message="Adding to redis : ${body}"&gt;&lt;/log&gt;
                  &lt;to uri="spring-redis://localhost:6379?serializer=#stringSerializer" /&gt;
              &lt;/pipeline&gt;
              &lt;pipeline&gt;
                  &lt;transform&gt;
                      &lt;method ref="insertBean" method="myBatchInsertion"&gt;&lt;/method&gt;
                  &lt;/transform&gt;
                  &lt;choice&gt;
                      &lt;when&gt;
                          &lt;simple&gt; ${body.size()} == ${properties:my.batch.size}&lt;/simple&gt;
                          &lt;log message="Going to insert my batch in database" /&gt;
                          &lt;to uri="mybatis:batchInsert?statementType=InsertList"&gt;&lt;/to&gt;
            &lt;log message="Inserted in my table : ${in.header.CamelMyBatisResult}"&gt;&lt;/log&gt;
                          &lt;choice&gt;
                              &lt;when&gt;
                                  &lt;simple&gt;${properties:my.write.file} == true&lt;/simple&gt;
                                  &lt;bean beanType="com.***.***.processors.InsertToFile"
                                      method="processMy(${exchange}" /&gt;
                                  &lt;log message="Going to write to file : ${in.header.CamelFileName}" /&gt;
                                  &lt;to uri="file://?fileExist=Append&amp;amp;bufferSize=32768"&gt;&lt;/to&gt;
                              &lt;/when&gt;
                          &lt;/choice&gt;
                      &lt;/when&gt;
                  &lt;/choice&gt;
              &lt;/pipeline&gt;
          &lt;/multicast&gt;
      &lt;/route&gt;
  &lt;/routeContext&gt;
  </code></pre>
  
  <p>Below are the beans:</p>
  
  <pre><code>public class InsertBeanImpl {
    public  List&lt;Out&gt; myOutList = new CopyOnWriteArrayList&lt;Out&gt;();
  
    public List&lt;Out&gt; myBatchInsertion(Exchange exchange) {
          if (myOutList.size() &gt;= myBatchSize) {
              Logger.sysLog(LogValues.info,this.getClass().getName(),"Reached max PayLoad size : "+myOutList.size() + " , going to clear batch");
              myOutList.clear();
          }
          Out myOut = exchange.getIn().getBody(Out.class);
          Logger.sysLog(LogValues.APP_INFO, this.getClass().getName(), myOut.getMasterId()+" | "+"Adding to batch masterId : "+myOut.getMasterId());
          synchronized(myOut){
              myOutList.add(myOut);
          }
          Logger.sysLog(LogValues.info, this.getClass().getName(), "Count of batch : "+myOutList.size());
          return myOutList;
      }
  }
  
  
  
  public class SaveToFile {
      static String currentFileName = null;
      static int iSub = 0;
      String path;
      String absolutePath;
  
      @Autowired
      private Utility utility;
  
  
      public void processMy(Exchange exchange) {
          getFileName(exchange, currentFileNameSub, iSub);
      }
  
  
      public void getFileName(Exchange exchange, String outFile, int i) {
          exchange.getIn().setBody(getFromJson(exchange));
          path = (String) exchange.getIn().getHeader("path");
          Calendar date = null;
          date = new GregorianCalendar();
          NumberFormat format = NumberFormat.getIntegerInstance();
          format.setMinimumIntegerDigits(2);
          String pathSuffix = "/" + date.get(Calendar.YEAR) + "/"
                  + format.format((date.get(Calendar.MONTH) + 1)) + "/"
                      + format.format(date.get(Calendar.DAY_OF_MONTH));
          String fileName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
          double megabytes = 100 * 1024 * 1024;
          if (outFile != null) {
              if (!fileName.equals(outFile.split("_")[0])) {
                  outFile = null;
                  i = 0;
              }
          }
          if (outFile == null) {
              outFile = fileName + "_" + i;
          }
          while (new File(path + "/" + pathSuffix + "/" + outFile).length() &gt;= megabytes) {
              outFile = fileName + "_" + (++i);
          }
          absolutePath = path + "/" + pathSuffix + "/" + outFile;
          exchange.getIn().setHeader("CamelFileName", absolutePath);
      }
  
      public String getFromJson(Exchange exchange) {
          synchronized(exchange){
              List&lt;Out&gt; body = exchange.getIn().getBody(CopyOnWriteArrayList.class);
              Logger.sysLog(LogValues.info, this.getClass().getName(), "body &gt; "+body.size());
              String text = "";
              for (int i = 0; i &lt; body.size(); i++) {
                  Out msg = body.get(i);
                  text = text.concat(utility.convertObjectToJsonStr(msg) + "\n");
              }
              return text;
          }
  
      }
  }
  </code></pre>
  
  <p>As the processors are not synchronized and not thread safe, the route does not works as expected in case of multiple consumers.</p>
  
  <p>Can anybody tell how to make my route thread safe or synchronized?</p>
  
  <p>I tried making the processors synchronized, but it didn't helped. Any other way to do this?</p>