A sample code of module development which validates an XML File.
Place the corresponding XSD in the /usr/sap/<SID>/DVEB<>/j2ee/cluster/server0 folder on the XI server.
package
com.ibis.module;import
java.io.File;import
java.io.FileInputStream;import
java.io.IOException;import
java.io.InputStream;import
java.rmi.RemoteException;import
java.text.SimpleDateFormat;import
java.util.Calendar;import
java.util.Date;import
java.util.GregorianCalendar;import
java.util.Properties;import
javax.ejb.CreateException;import
javax.ejb.EJBException;import
javax.ejb.SessionBean;import
javax.ejb.SessionContext;import
javax.xml.parsers.ParserConfigurationException;import
javax.xml.parsers.SAXParser;import
javax.xml.parsers.SAXParserFactory;import
org.xml.sax.Attributes;import
org.xml.sax.InputSource;import
org.xml.sax.SAXException;import
org.xml.sax.SAXNotRecognizedException;import
org.xml.sax.SAXNotSupportedException;import
org.xml.sax.SAXParseException;import
org.xml.sax.XMLReader;import
org.xml.sax.helpers.DefaultHandler;import
org.xml.sax.helpers.XMLReaderFactory;import
com.sap.aii.af.mp.module.Module;import
com.sap.aii.af.mp.module.ModuleContext;import
com.sap.aii.af.mp.module.ModuleData;import
com.sap.aii.af.mp.module.ModuleException;import
com.sap.aii.af.ra.ms.api.InvalidParamException;import
com.sap.aii.af.ra.ms.api.Message;import
com.sap.aii.af.ra.ms.api.XMLPayload;import
com.sap.aii.af.service.auditlog.Audit;import
com.sap.aii.af.service.auditlog.AuditDirection;import
com.sap.aii.af.service.auditlog.AuditLogStatus;import
com.sap.aii.af.service.auditlog.AuditMessageKey;import
com.sap.aii.af.service.cpa.Channel;import
com.sap.aii.af.service.trace.Trace;import
com.sap.engine.lib.xml.parser.ParserException;/**
* @ejbLocal <{com.ibis.module.XMLValidationLocal}> * @ejbLocalHome <{com.ibis.module.XMLValidationLocalHome}> * @stateless * @transactionType Container */public
class XMLValidationBean extends DefaultHandler implements SessionBean, Module{
/** * */ static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; public static final String VERSION_ID = "ValidateXMLs.java"; private static final Trace TRACE = new Trace(VERSION_ID); private SessionContext myContext; public static boolean isValid = true; //public static ByteArrayOutputStream baos = new ByteArrayOutputStream(); public StringBuffer sb = new StringBuffer(); public static StringBuffer errorLogText = new StringBuffer(); public static String errorLogText1 = new String(); public static StringBuffer errorLogDate = new StringBuffer(); public static StringBuffer errorLogTime = new StringBuffer(); public static StringBuffer errorLogType = new StringBuffer("INVALID"); //public static StringBuffer baos = new StringBuffer(); public static Object obj = null; public static Message msg = null; public static AuditMessageKey myAuditMsgKey = null; private static final long serialVersionUID = 1L; public ModuleData process(ModuleContext moduleContext,
ModuleData inputModuleData)
throws ModuleException{
String SIGNATURE =
"process(ModuleContext moduleContext, ModuleData inputModuleData)";TRACE.entering(
SIGNATURE,
new Object[] { moduleContext, inputModuleData }); // Access the XI message. I.e. this module must be placed in the module // chain // behind a module that sets an XI message as principal data.isValid =
true;sb =
new StringBuffer();String prop = System.getProperty(
"javax.xml.parsers.SAXParserFactory"); try{
obj = inputModuleData.getPrincipalData();
msg = (Message) obj;
// Prepare audit log entrymyAuditMsgKey =
new AuditMessageKey(msg.getMessageId(),
AuditDirection.OUTBOUND);
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.SUCCESS,
"Invenio-solutions: Method process of Module XMLValidation Called");Audit.flushAuditLogEntries(myAuditMsgKey);
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.SUCCESS,
"The system property is "+prop);Audit.flushAuditLogEntries(myAuditMsgKey);
//// Determine process context // ProcessContext myProcessContext = ProcessContextFactory // .getInstance() // .createProcessContext( // ProcessContextFactory.getParamSet().message(msg)); // // Update processing state // m_spiManagedConnectionFactory.getXiConfiguration() // .getMonitoringManager().reportProcessStatus( // aSpiManagedConnection.getChannel() // .getAdapterNamespace(), // aSpiManagedConnection.getChannel().getAdapterType(), // ChannelDirection.RECEIVER, ProcessState.OK, // "Message received for synchronous processing.", // myProcessContext);}
catch (Exception e){
TRACE.catching(SIGNATURE, e);
if (obj != null){
TRACE.errorT(
SIGNATURE,
"Input ModuleData does not contain an object that implements the XI message interface. The object class is: {0}", new Object[] { obj.getClass().getName()});// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Input ModuleData does not contain an object that implements the XI message interface.");
// Audit.flushAuditLogEntries(myAuditMsgKey);
}
else{
TRACE.errorT(
SIGNATURE,
"Input ModuleData contains only null as XI message");// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Input ModuleData contains only null as XI message");
// Audit.flushAuditLogEntries(myAuditMsgKey);
}
ModuleException me =
new ModuleException(e);TRACE.throwing(SIGNATURE, me);
throw me;}
// Read the channel ID, channel and the module configurationString cid =
null;String mode =
null;Channel channel =
null;XMLPayload xmlPayload = msg.getDocument();
byte[] content = xmlPayload.getContent(); //boolean isOrder = checkOrderType(content); if (xmlPayload != null){
// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Validation will start now...");
// Audit.flushAuditLogEntries(myAuditMsgKey);
//validate the fileisValid = validateXml(content);
if (isValid){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.SUCCESS,
"File is Valid");Audit.flushAuditLogEntries(myAuditMsgKey);
}
else{
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Invalid File was received by the Communication Channel");Audit.flushAuditLogEntries(myAuditMsgKey);
//just attach the invalid part to content}
this.createDocument(content);// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Canonical structure formation for website orders will start now...");
// Audit.flushAuditLogEntries(myAuditMsgKey);
//create document for both invalid and valid files// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Structure formed successfully");
// Audit.flushAuditLogEntries(myAuditMsgKey);
try{
//xmlPayload.setContent(baos.toByteArray());xmlPayload.setContent(sb.toString().getBytes());
inputModuleData.setPrincipalData(msg);
TRACE.debugT(
SIGNATURE,
"Document creation finished sucessfully.");// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "XI Message was created successfully.");
//Audit.flushAuditLogEntries(myAuditMsgKey);}
catch (InvalidParamException e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getMessage());Audit.flushAuditLogEntries(myAuditMsgKey);
}
}
//System.setProperty("javax.xml.parsers.SAXParserFactory",prop);Properties sysProps = System.getProperties();
sysProps.remove(
"javax.xml.parsers.SAXParserFactory");Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.SUCCESS,
"Restored :The system property is "+System.getProperty("javax.xml.parsers.SAXParserFactory"));Audit.flushAuditLogEntries(myAuditMsgKey);
//release memory //baos.close(); //baos = null; //sb = null;TRACE.exiting(SIGNATURE);
return inputModuleData;}
public void ejbCreate() throws CreateException{
}
public static boolean checkOrderType(byte[] content){
boolean isOrder = true;String cont =
new String(content); if (cont.indexOf("CDFOrder") != -1){
isOrder =
false;}
cont =
null; //System.out.println("Order is the type: " + isOrder); return isOrder;}
public void ejbActivate() throws EJBException, RemoteException{
}
public void ejbPassivate() throws EJBException, RemoteException{
}
public void ejbRemove() throws EJBException, RemoteException{
}
public void setSessionContext(SessionContext context) throws EJBException, RemoteException{
myContext = context;
}
public void createDocument(byte[] xmlName){
InputSource source1 =
new InputSource(new java.io.ByteArrayInputStream(xmlName)); //String schemaFeature = // "http://apache.org/xml/features/validation/schema";// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Parsing will start now...");
try{
//System.setProperty("javax.xml.parsers.SAXParserFactory","org.apache.xerces.jaxp.SAXParserFactoryImpl");System.setProperty(
"javax.xml.parsers.SAXParserFactory", "com.sap.engine.lib.jaxp.SAXParserFactoryImpl");Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.SUCCESS,
"Setting system property to com.sap.engine.lib.jaxp.SAXParserFactoryImpl");Audit.flushAuditLogEntries(myAuditMsgKey);
SAXParserFactory f = SAXParserFactory.newInstance();
f.setValidating(
false);f.setNamespaceAware(
false);SAXParser p = f.newSAXParser();
// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Parsing ...");
p.parse(source1,
this); //System.out.println("Parsing finished"); //End the document //System.out.println(new String(baos.toByteArray()));}
catch (SAXNotRecognizedException e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getException());}
catch (SAXNotSupportedException e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getException());}
catch (ParserConfigurationException e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getStackTrace());}
catch (SAXException e){
StackTraceElement[] st = e.getStackTrace();
String stack =
new String(); for(int i=0;i<st.length;i++){
stack = stack+ st[i];
}
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + stack); //create a log if notdocsb =
new StringBuffer() ;sb.append(
"<?xml version=\"1.0\" encoding=\"utf-8\" ?><Messages> "); //sb.append(new String(xmlName)); //append INVALIDString output;
SimpleDateFormat formatter;
formatter =
new SimpleDateFormat("yyyy-MM-dd");Date trialdate =
new Date();output = formatter.format(trialdate);
formatter =
new SimpleDateFormat("HH:mm:ss");String time = formatter.format(trialdate);
StringBuffer errorLogDate =
new StringBuffer( "<Date>"+ output
+
"</Date>");StringBuffer errorLogTime =
new StringBuffer( "<Time>"+ time
+
"</Time>"); try{
sb.append(
"<ErrorLog>"+ errorLogDate
+ errorLogTime
+
"<Type>INVALID</Type><Text>Parsing Exception</Text></ErrorLog>"); // baos.write( // ("<ErrorLog>" // + errorLogDate // + errorLogTime // + "<Type>INVALID</Type><Text>" // + "Validation of XML against XSD failed.</Text></ErrorLog>") // .getBytes());}
catch (Exception e1){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end doc : " + e1.getStackTrace());}
catch (Throwable e1){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end doc thro: " + e1.getStackTrace());}
sb.append(
"</Messages>");}
catch (IOException e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getMessage());}
//Audit.flushAuditLogEntries(myAuditMsgKey);}
public boolean validateXml(byte[] xmlName){
// preparing the XML file as a input sourceInputSource source =
new InputSource(new java.io.ByteArrayInputStream(xmlName)); //String parserClass = "org.apache.xerces.parsers.SAXParser";String parserClass =
"com.sap.engine.lib.xml.parser.SAXParser";String validationFeature =
"http://xml.org/sax/features/validation";String schemaFeature =
"http://apache.org/xml/features/validation/schema"; //String namespacesFeature = "http://xml.org/sax/features/namespaces"; //String noNamespaceProperty ="http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"; //String dynamicFeature = "http://apache.org/xml/features/validation/dynamic"; //XMLValidationBean vl = new XMLValidationBean(); try{
XMLReader r = XMLReaderFactory.createXMLReader(parserClass);
r.setFeature(validationFeature,
true); //r.setFeature(namespacesFeature,true); //r.setFeature(dynamicFeature,true);r.setFeature(schemaFeature,
true);r.setErrorHandler(
this);//
// if(checkOrderType(xmlName))
// r.setProperty( "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation" , "EDItX_TradeOrder_V1.1.xsd");
// else
// r.setProperty( "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation" , "EDItX_TradeCDFOrder_V1.1.xsd");
//
r.parse(source);
//System.out.println("ValidateXML :" + isValid);}
catch (SAXException e){
isValid =
false;errorLogText1 =
"";errorLogText1 =
"Validation of XML against XSD failed";Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getCause());}
catch (IOException e){
isValid =
false;Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getMessage());}
catch (Exception e){
isValid =
false;errorLogText1 =
"";errorLogText1 =
"Parser Exception";Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getCause());}
// catch (Throwable e)
// {
// isValid = false;
// errorLogText1 = "";
// errorLogText1="Parsing Exception";
// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.ERROR,
// "Exception : " + e.getMessage());
// }
//Audit.flushAuditLogEntries(myAuditMsgKey); return isValid;}
/** * =========================================================== Methods * Overriding in SAX Default Handler * =========================================================== */ /** * Receive notification of the beginning of the document. By overriding this * method in a subclass to take specific actions at the beginning of a * document (such as allocating the root node of a tree or creating an * output file) */ public void startDocument() throws SAXException{
// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "Inside StartDocument()");
try{
sb.append(
"<?xml version=\"1.0\" encoding=\"utf-8\" ?><Messages> "); // baos.write( // ("<?xml version=\"1.0\" encoding=\"utf-8\" ?> ").getBytes()); // baos.write(("<Message>").getBytes()); //baos.flush();}
// catch (IOException e) // { // // TODO Auto-generated catch block // e.printStackTrace(); // } catch (Throwable e){
StackTraceElement[] st = e.getStackTrace();
String stack =
new String(); for(int i=0;i<st.length;i++){
stack = stack+ st[i];
}
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception : " + e.getCause()); //System.out.println("Exception " + e.getMessage());}
// System.out.println(new String(baos.toByteArray())); //System.out.println("<Message>"); //Audit.flushAuditLogEntries(myAuditMsgKey); //System.out.println("End");}
/** * Receive notification of the end of the document. By overriding this * method in a subclass to take specific actions at the end of a document * (such as finalizing a tree or closing an output file) */ public void endDocument() throws SAXException{
// Audit.addAuditLogEntry(
// myAuditMsgKey,
// AuditLogStatus.SUCCESS,
// "EndDocument() called");
//
// sb = new StringBuffer() ;
// sb.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?><Messages> ");
//
// sb.append(new String(xmlName));
if(!isValid) //append INVALID{
String output;
SimpleDateFormat formatter;
formatter =
new SimpleDateFormat("yyyy-MM-dd");Date trialdate =
new Date();output = formatter.format(trialdate);
formatter =
new SimpleDateFormat("HH:mm:ss");String time = formatter.format(trialdate);
StringBuffer errorLogDate =
new StringBuffer( "<Date>"+ output
+
"</Date>");StringBuffer errorLogTime =
new StringBuffer( "<Time>"+ time
+
"</Time>"); try{
sb.append(
"<ErrorLog>"+ errorLogDate
+ errorLogTime
+
"<Type>INVALID</Type><Text>Validation of XML against XSD failed.</Text></ErrorLog>"); // baos.write( // ("<ErrorLog>" // + errorLogDate // + errorLogTime // + "<Type>INVALID</Type><Text>" // + "Validation of XML against XSD failed.</Text></ErrorLog>") // .getBytes());}
catch (Exception e1){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end doc : " + e1.getStackTrace());}
catch (Throwable e1){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end doc thro: " + e1.getStackTrace());}
}
sb.append(
"</Messages>");}
/** * Receive notification of the start of an element. By overriding this * method in a subclass to take specific actions at the start of each * element (such as allocating a new tree node or writing output to a file) * @param namespaceURI The URi * @param name The local name * @param qName The qualified name * @param attrs The attributes associated * @throws SAXException */ public void startElement(String namespaceURI,
String name,
String qName,
Attributes attrs)
throws SAXException{
try{
sb.append(
"<" + name); //baos.write(("<" + name).getBytes()); //baos.flush(); if (name.equals("CDFOrder") || name.equals("Order")){
for (int i = 0; i < attrs.getLength(); i++){
sb.append(
" "+ attrs.getQName(i)
+
"=\""+ attrs.getValue(i)
+
"\""); // baos.write( // (" " // + attrs.getQName(i) // + "=\"" // + attrs.getValue(i) // + "\"") // .getBytes());}
}
sb.append(
">"); // baos.write(">".getBytes());}
catch (Exception e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in start: " +name+" " + e.getStackTrace());}
catch (Throwable e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in start thro: "+name+" " + e.getStackTrace()); //System.out.println("Exception " + e.getCause());}
// Audit.flushAuditLogEntries(myAuditMsgKey); //System.out.println(new String(baos.toByteArray())); //System.out.println("<" + name + ">");}
/** * Receive notification of the end of an element. By overriding this * method in a subclass to take specific actions at the end of each * element (such as allocating a new tree node or writing output to a file) * @param uri The URi * @param name The local name * @param qName The qualified name * * @throws SAXException */ public void endElement(String uri, String name, String qName) throws SAXException{
try{
sb.append(
"</" + name + ">"); //baos.write(("</" + name + ">").getBytes()); //baos.flush();}
catch (Exception e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end : "+name+" " + e.getStackTrace()); //throw new SAXException(e);}
catch (Throwable e){
Audit.addAuditLogEntry(
myAuditMsgKey,
AuditLogStatus.ERROR,
"Exception in end thro: "+name+" " + e.getStackTrace()); //throw new SAXException(e.getStackTrace());}
// Audit.flushAuditLogEntries(myAuditMsgKey); //System.out.println(new String(baos.toByteArray())); //System.out.println("</" + name + ">");}
public String replaceSpecial(String s){
s = s.replaceAll(
"<","<");s = s.replaceAll(
">",">");s = s.replaceAll(
"'","'");s = s.replaceAll(
"\"",""");s = s.replaceAll(
"&","&"); return s;}
/** * This method has handling for escape characters in the value part * @param buf The array containing value * @param offset * @param len * @throws SAXException * */ public void characters(char buf[], int offset, int len) throws SAXException{
String s =
new String(buf, offset, len); if (null != s){
s = replaceSpecial(s);
try{
sb.append(s);
//baos.write(s.getBytes()); //baos.flush();}
catch (Exception e){
//// Audit.addAuditLogEntry( //// myAuditMsgKey, //// AuditLogStatus.ERROR, // "Exception : " + e.getMessage());}
catch (Throwable e){
// Audit.addAuditLogEntry( // myAuditMsgKey, // AuditLogStatus.ERROR, // "Exception : " + e.getMessage());}
//Audit.flushAuditLogEntries(myAuditMsgKey); //System.out.println(s);}
}
/** * @param args */ public static void main(String[] args){
//System.setProperty("jaxp.debug","1"); byte[] file = null; try{
file = getBytesFromFile(
new File("CDForderValid.xml"));}
catch (IOException e){
// Audit.addAuditLogEntry( // myAuditMsgKey, // AuditLogStatus.ERROR, // "Exception : " + e.getMessage());}
XMLValidationBean vl =
new XMLValidationBean(); boolean Valid = vl.validateXml(file); //System.out.println("File validate: " + XMLValidationBean.isValid); //if (ValidateXMLs.isValid)vl.createDocument(file);
//System.out.println(sb.toString());}
public static byte[] getBytesFromFile(File file) throws IOException{
InputStream is =
new FileInputStream(file); // Get the size of the file long length = file.length(); // You cannot create an array using a long type. // It needs to be an int type. // Before converting to an int type, check // to ensure that file is not larger than Integer.MAX_VALUE. if (length > Integer.MAX_VALUE){
// File is too large}
// Create the byte array to hold the data byte[] bytes = new byte[(int) length]; // Read in the bytes int offset = 0; int numRead = 0; while (offset < bytes.length&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
{
offset += numRead;
}
// Ensure all the bytes have been read in if (offset < bytes.length){
throw new IOException( "Could not completely read file " + file.getName());}
// Close the input stream and return bytesis.close();
return bytes;}
/* (non-Javadoc)* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
*/
public void error(SAXParseException e) throws SAXException{
isValid =
false; //System.out.println("Error: ");printInfo(e);
}
/* (non-Javadoc)* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
*/
public void fatalError(SAXParseException e) throws SAXException{
//System.out.println("Fatal error: ");printInfo(e);
}
/* (non-Javadoc)* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
*/
public void warning(SAXParseException e) throws SAXException{
//System.out.println("Warning: ");printInfo(e);
}
private void printInfo(SAXParseException e){
errorLogText.append(
"Error at Line : "+ e.getLineNumber()
+
" Column : "+ e.getColumnNumber()
+
" Message : "+ e.getMessage()
+
"\n");isValid =
false;System.out.println(
" Public ID: " + e.getPublicId());System.out.println(
" System ID: " + e.getSystemId());System.out.println(
" Line number: " + e.getLineNumber());System.out.println(
" Column number: " + e.getColumnNumber());System.out.println(
" Message: " + e.getMessage());}
}