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() > 0) {
tempTestStringForDirectory = tempTestStringForDirectory + "\n Got order\n" + "\n" + fileName + "\n" + "got order\n";
for (int x = 0; x < orderNodeList.getLength(); x++) {
System.out.println(orderNodeList.item(x).getAttributes().getNamedItem("orderId").getNodeValue());
}
}
NodeList descriptionNodeList = doc.getElementsByTagName("Description");
if (descriptionNodeList.getLength() > 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");
}
}
n 개의 파일에 대한 n 개의 스레드가 좋지 않습니까? 그 시스템을 크래시하지 않거나 너무 많은 쓰레드 오류를주지 않을까요? 프로그램을 멀티 스레드로 만들려고합니다. 내가 뭘 놓치고 있는지 모르겠다. 내 프로그램에는 하나의 파일이 전달되었는지 또는 디렉토리가 통과되었는지를 알기위한 논리가 있습니다. 하나의 파일이 전달되면 하나의 스레드에서 문제가 없습니다. 그러나 디렉토리가 전달되면 어떻게해야합니까? 내 listFilesForFolder 메서드에서 스레드를 만들어야합니까? 스레드는 항상 main 메소드에서 시작 되었습니까? 아니면 다른 메소드에서 시작할 수 있습니까? 또한,이 프로그램은 다른 사람들이 사용하게 될 것이므로 쓰레드를 적절하게 처리하는 것이 제 일이되어야합니다. 그들이해야 할 일은 내 프로그램을 사용하는 것뿐입니다. 그래서 스레드 로직이 메인 메소드에 속해서는 안되며 listFilesForFolder는 내 프로그램의 시작점이라고 생각합니다. 도와 줘서 고마워.다중 스레딩, 여러 파일 읽기 및 병렬로 서버에 보내기
는, 일반적으로 병목 대역폭이 될 것입니다, 그래서 멀티 스레딩은 아마 많은 도움이되지 않습니다 . 그리고 스레드의 실질적인 제한은 일반적으로 CPU의 코어 수입니다. – SJuan76
요구 사항은 프로그램을 멀티 스레드로 만드는 것입니다. –
그럴 경우, 너무 많은 스레드를 만드는 것보다 나은 방법은 고정 된 숫자로 설정하는 것입니다 (일부 초기화 매개 변수로 정의 할 수 있음). 프로그램의 초기 부분은 파일 및 스레드 목록을 작성합니다. 이전 업로드가 완료되면 스레드가 목록에서 다음 파일을 가져 와서 업로드합니다. – SJuan76