title: Multithreading, Read multiple files and send them to server in parallel
body: <pre><code>public class SOAPClient implements Runnable {
  
      /*
       * endpoint url, the address where soap xml will be sent. It is hard coded
       * now, later on to be made configurable
       */
      private String endpointUrl = "";
      /*
       * This is for debugging purposes Message and response are written to the
       * fileName
       */
      static String fileName = "";
  
      /*
       * serverResponse This is a string representation of the response received
       * from server
       */
      private String serverResponse = null;
  
      public String tempTestStringForDirectory = "";
  
      /*
       * A single file or a folder maybe provided
       */
      private File fileOrFolder;
  
      public SOAPClient(String endpointURL, File fileOrFolder) {
          this.endpointUrl = endpointURL;
          this.fileOrFolder = fileOrFolder;
          serverResponse = null;
      }
  
      /*
       * Creats a SOAPMessage out of a file that is passed
       * 
       * @param fileAddress - Contents of this file are read and a SOAPMessage is
       * created that will get sent to the server. This is a helper method. Is
       * this step (method, conversion) necessary? set tempSoapText = XML String,
       * currently getting from file, but it can be a simple string
       */
      private SOAPMessage xmlStringToSOAPMessage(String fileAddress) {
          System.out.println("xmlStringToSoap()");
          // Picking up this string from file right now
          // This can come from anywhere
          String tempSoapText = readFileToString(fileAddress);
          SOAPMessage soapMessage = null;
          try {
              // Create SoapMessage
              MessageFactory msgFactory = MessageFactory.newInstance();
              SOAPMessage message = msgFactory.createMessage();
              SOAPPart soapPart = message.getSOAPPart();
              // Load the SOAP text into a stream source
              byte[] buffer = tempSoapText.getBytes();
              ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
              StreamSource source = new StreamSource(stream);
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              // Set contents of message
              soapPart.setContent(source);
              message.writeTo(out);
              soapMessage = message;
          } catch (SOAPException e) {
              System.out.println("soapException xmlStringToSoap()");
              System.out.println("SOAPException : " + e);
          } catch (IOException e) {
              System.out.println("IOException xmlStringToSoap()");
              System.out.println("IOException : " + e);
          }
          return soapMessage;
      }
  
      /*
       * Reads the file passed and creates a string. fileAddress - Contents of
       * this file are read into a String
       */
      private String readFileToString(String fileAddress) {
          FileInputStream stream = null;
          MappedByteBuffer bb = null;
          String stringFromFile = "";
          try {
              stream = new FileInputStream(new File(fileAddress));
              FileChannel fc = stream.getChannel();
              bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
              stringFromFile = Charset.defaultCharset().decode(bb).toString();
          } catch (IOException e) {
              System.out.println("readFileToString IOException");
              e.printStackTrace();
          } finally {
              try {
                  stream.close();
              } catch (IOException e) {
                  System.out.println("readFileToString IOException");
                  e.printStackTrace();
              }
          }
          return stringFromFile;
      }
  
      /*
       * soapXMLtoEndpoint sends the soapXMLFileLocation to the endpointURL
       */
      public void soapXMLtoEndpoint(String endpointURL, String soapXMLFileLocation) throws SOAPException {
          SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
          SOAPMessage response = connection.call(xmlStringToSOAPMessage(soapXMLFileLocation), endpointURL);
          connection.close();
          SOAPBody responseBody = response.getSOAPBody();
          SOAPBodyElement responseElement = (SOAPBodyElement) responseBody.getChildElements().next();
          SOAPElement returnElement = (SOAPElement) responseElement.getChildElements().next();
          if (responseBody.getFault() != null) {
              System.out.println("fault != null");
              System.out.println(returnElement.getValue() + " " + responseBody.getFault().getFaultString());
          } else {
              serverResponse = returnElement.getValue();
              System.out.println(serverResponse);
              System.out.println("\nfault == null, got the response properly.\n");
          }
      }
  
      /*
       * This is for debugging purposes. Writes string to a file.
       * 
       * @param message Contents to be written to file
       * 
       * @param fileName the name of the
       */
      private static void toFile(String message, String fileName) {
          try {
              FileWriter fstream = new FileWriter(fileName);
              System.out.println("printing to file: ".concat(fileName));
              BufferedWriter out = new BufferedWriter(fstream);
              out.write(message);
              out.close();
          } catch (Exception e) {
              System.out.println("toFile() Exception");
              System.err.println("Error: " + e.getMessage());
          }
      }
  
      /*
       * Using dom to parse the xml. Getting both orderID and the description.
       * 
       * @param xmlToParse XML in String format to parse. Gets the orderID and
       * description Is the error handling required? What if orderID or
       * description isn't found in the xmlToParse? Use setters and getters?
       * 
       * @param fileName only for debuggining, it can be safely removed any time.
       */
      private void domParsing(String xmlToParse, String fileName) {
          if (serverResponse == null) {
              return;
          } else {
              try {
                  System.out.println("in domParsing()");
                  DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                  DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                  System.out.println("serverResponse contains fault");
                  Document doc = dBuilder.parse(new InputSource(new StringReader(serverResponse)));
                  doc.getDocumentElement().normalize();
                  NodeList orderNodeList = doc.getElementsByTagName("Order");
                  if (orderNodeList.getLength() &gt; 0) {
                      tempTestStringForDirectory = tempTestStringForDirectory + "\n Got order\n" + "\n" + fileName + "\n" + "got order\n";
                      for (int x = 0; x &lt; orderNodeList.getLength(); x++) {
                          System.out.println(orderNodeList.item(x).getAttributes().getNamedItem("orderId").getNodeValue());
                      }
                  }
                  NodeList descriptionNodeList = doc.getElementsByTagName("Description");
                  if (descriptionNodeList.getLength() &gt; 0) {
                      System.out.println("getting description");
                      String tempDescriptionString = descriptionNodeList.item(0).getTextContent();
                      System.out.println(tempDescriptionString);
                      tempTestStringForDirectory = tempTestStringForDirectory + "\n Got description" + "\n" + fileName + "\n" + tempDescriptionString + "\n";
                  }
              } catch (Exception e) {
                  System.out.println("domParsing() Exception");
                  e.printStackTrace();
              }
          }
      }
  
      /*
       * Reads a single file or a whole directory structure
       */
      private void listFilesForFolder(final File fileOrFolder) {
          String temp = "";
          if (fileOrFolder.isDirectory()) {
              for (final File fileEntry : fileOrFolder.listFiles()) {
                  if (fileEntry.isDirectory()) {
                      listFilesForFolder(fileEntry);
                  } else {
                      if (fileEntry.isFile()) {
                          temp = fileEntry.getName();
                          try {
                              soapXMLtoEndpoint(endpointUrl, fileOrFolder.getAbsolutePath() + "\\" + fileEntry.getName());
                              domParsing(serverResponse, fileEntry.getName());
                          } catch (SOAPException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              }
          }
          if (fileOrFolder.isFile()) {
              temp = fileOrFolder.getName();
              System.out.println("this is a file");
              System.out.println(temp);
              try {
                  soapXMLtoEndpoint(endpointUrl, fileOrFolder.getAbsolutePath());
              } catch (SOAPException e) {
                  e.printStackTrace();
              }
              domParsing(serverResponse, temp);
          }
      }
  
      @Override
      public void run() {
          listFilesForFolder(fileOrFolder);
          toFile(tempTestStringForDirectory, "test.txt");
      }
  
      public static void main(String[] args) {
          String tempURLString = ".../OrderingService";
          String tempFileLocation = "C:/Workspace2/Test5/";
          SOAPClient soapClient = new SOAPClient(tempURLString, new File(tempFileLocation));
          Thread thread = new Thread(soapClient);
          thread.start();
          System.out.println("program ended");
      }
  }
  </code></pre>
  
  <p>I think n threads for n files would be bad? Wouldn't that crash the system, or give too many threads error?
  I'm trying to make my program multi threaded. I don't know what I am missing. My program has a logic to know if a single file is passed or a directory is passed. One thread is fine if a single file is passed. But what should I do if a directory is passed? Do I need to create threads in my listFilesForFolder method? Are the threads always started from the main method, or can they be started from other methods? Also, this program is going to be used by other people, so it should be my job to handle the threads properly. All they should have to do is be using my program. So I feel that the thread logic should not belong in the main method but rather listFilesForFolder which is the starting point of my program. Thank you for your help.</p>