2024년 4월 19일 금요일

자바 HttpURLConnection으로 PI/PO Directory API 웹서비스(SOAP) 호출하는 방법

다이나믹웹프로젝트(JAVA EE)+톰켓을 사용한 이클립스 환경에서의 WSDL파일을 제너레이션해서 웹서비스 호출을 위한 개발은 진행했으나 순수 자바프로젝트에서 동일한 방식으로 진행하려니 웹서비스 프레임워크나 톰켓 버젼에서 문제 발생되어 원인 찾아 셋팅하는것만으로도 시간을 많이 소비될것 같은 생각이 듬

알고 있는 웹서비스 프레임워크는 AXIS(Deprecated),AXIS2,CXF이고 WSDL파일을 제너레이션 하게되면 생되는 자바파일도 늘어나고 그래서 REST로 PI/PO의 Directory API를 웹서비스 호출하려고 함

웹서비스 호출 정보 확인

호출하려는 PI/PO 웹서비스 정보는 NWA > Configuration > Connectivity > Single Service Administration 메뉴클릭 후 서비스명을 검색 후 확인되는 웹서비스정보를 확인하면 됨

만약 해당 메뉴 접근을 못하는 경우 PO담당자한테 WSDL+호출URL정보를 제공받아 SOAP UI에 임포트하거나 WSDL URL로 웹서비스 정보를 확인할수 있음

위 경로를 통해 자바에서 REST로 호출하는 SOAP구조와 URL로 확인하고 웹서비스 프로그램으로 미리 호출테스트를 해보는것도 좋을것 같음

개인적으로 PO메뉴보다 SOAP UI에서 확인되는 요청데이터가 불필요한 태그가 없어서 좋은데 보통 SOAP방식으로 호출되는 XML데이터는 아래와 같은데 SAP PO에서 제공하는 웹서비스마다 XML구조가 다름
⁠<soapenv:Envelope xmlIns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlIns:bas="http://sap.com/xi/BASIS">
 <soapenv:Header/>
 <soapenv:Body>
  <bas:BusinessSystemQueryRequest>
  </bas:BusinessSystemQueryRequest>
 </soapenv:Body>
</soapenv:Envelope>

REST to SOAP(WSDL) 호출소스 구현
SOAP호출 후에 SOAP구조(XML)로 리턴을 받아야 해서 인터넷에서 아래 샘플소스를 찾아 json-simple-2.1.2.jar를 클래스패스로 추가했는 이 버전에서 지원안하는 소스인듯
⁠JSONParser jsonParser = new JSONParser();
JSONObject soapResult = (JSONObject) jsonParser.parse(node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue());

그래서 구현한 소스는 아래와 같음
SoapClient.java
⁠public class SoapClient{
private String WSDL_URL;
private String SOAP_ACTION;
private String AUTH_STRING;
//웹서비스 호출정보 셋팅
public SoapClient(String soapUrl, String soapAction){
WSDL_URL = soapUrl;
String authString = "<po아이디>:<po패스워드>";
try{
byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes("UTF-8"));
AUTH_STRING = new String(authEncBytes);
}catch(UnsupportedEncodingException e){
e.printStackTrace();
}
}
//웹서비스 호출
public String callWebService(String soapMessage) throws IOException{
//HTTP 연결 설정
URL url = new URL(WSDL_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
connection.setRequestProperty("SOAPAction",SOAP_ACTION);
connection.setRequestProperty("Authorization","Basic"+AUTH_STRING);
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);
connection.setDoOutput(true);

//SOAP 메시지 전송
try(PrintWriter pw = new PrintWriter(connection.getOutputStream())){
pw.print(soapMessage);
}

//응답받기
try{InputStream inputStream = connection.getInputStream()){
String xml = "no data";
InputStreamReader isw = new InputStreamReader(inutStream);

BufferedReader br = new BuffereReader(isw);
StringBuilder sb = new StringBuilder();
Strng line;
while((line = br.readLine()) != null){
sb.append(line+"\n");
}
br.close();

xml = sb.toString();

return xml
}
}
//웹서비스 호출 후리턴 데이터 XML파싱
public NodeList parseXML(String response, String tag) throws Exception{
//XML 문서 생성
DocumentBuilderFactory factory = DocumentBuilderFactory.netInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(response)));

//XML 데이터 파싱
NodeList nodes = docunet.getElementsByTagName(tag);

return nodes;
}
public static void main(String[] args){
String msgId = "메시지키";
String soapUrl = "SOAP 호출 URL";
String soapAction = "";
String soapMessage = "요청 XML메시지";

try{
SoapClient sc = new SoapClient(soapUrl, soapAction);
String response = sc.callWebService(soapMessage);

//XML 데이터 파싱
NodeList nodes = sc.parseXML(response, "m7:messageKey");
List<String>stockQuotes = new ArrayList<String>();
for(int i=0; i<nodes.getLengh(); i++){
Node node = nodes.item(i);
stockQuotes.add(node.getTextContent());
}

//결과출력
for(String stockQuote : stockQuotes) { System.out.println(stockQuote);}
}catch(Exception e){
e.printStackTrace();
}
}
}

댓글 없음:

댓글 쓰기