# CreditReport.jws Sample

This topic inludes the source code for the CreditReport.jws Sample.

## Sample Location

This sample is located in the following directory in your WebLogic Workshop installation:

BEA_HOME/weblogic81/samples/workshop/SamplesApp/WebServices/creditReport/

## Sample Source Code

`001 package creditReport; 002 003 /** 004 * <p>Credit reporting service. This service simulates constructing 005 * a credit report from multiple secondary sources of information. 006 * It uses two external services, one representing a bank and the 007 * other representing the Internal Revenue Service (IRS).</p> 008 * 009 * <p>The @jws:conversation-lifetime max-idle-time tag controls how 010 * long a conversational instance of this service will survive without 011 * seeing activity.</p> 012 * 013 * <p>Conversations represent resources: they shouldn't be left around.</p> 014 * @common:target-namespace namespace="http://workshop.bea.com/CreditReport" 015 * @jws:conversation-lifetime max-age="1 hour" max-idle-time="30 minutes" 016 * @common:xmlns namespace="http://openuri.org/bea/samples/workshop/creditReport" prefix="ns0" 017 */ 018 019 020 public class CreditReport implements com.bea.jws.WebService 021 { 022 /** 023 * @common:control 024 */ 025 private creditReport.IRSControl irsControl; 026 027 /** 028 * @common:control 029 */ 030 private creditReport.BankControl bankControl; 031 032 /* 033 * <p>ReportResult is an inner class used to represent a complete 034 * credit report. It is used to return report responses to 035 * the client.</p> 036 * 037 * <p>Inner classes that are used outside the parent class 038 * MUST be declared "public static" and they MUST have 039 * a public no-argument constructor.</p> 040 */ 041 public static class ReportResult implements java.io.Serializable 042 { 043 public String bank; 044 public String tax; 045 046 public ReportResult() {} 047 } 048 049 050 051 052 053 /** 054 * <p>Here we declare some persistent storage used 055 * to store intermediate results.<p> 056 * 057 * <p>All member variables of the Java class become 058 * persistent in the presence of a @common:conversation 059 * start tag on one or more methods.</p> 060 */ 061 public String taxReport = null; 062 public String bankReport = null; 063 064 public Callback callback; 065 066 /** 067 * <p>A Service can have an inner interface called 068 * Callback if it wants to have automatic (and WSDL) 069 * support for sending asynchronous messages back to 070 * the client.</p> 071 * 072 * <p>The methods in the callback interface are published in 073 * the .wsdl file for this service.</p> 074 * 075 * <p>Note that callbacks are asynchronous messages to the 076 * client. It may not be possible for these messages 077 * to pass through firewalls.</p> 078 */ 079 public interface Callback 080 { 081 /** 082 * <p>We call this method whenever we get some new data, to 083 * tell our client what kind of new data we have. We 084 * don't transmit the complete data, just a status 085 * message.</p> 086 * 087 * <p>We've declared this as a buffered method so that 088 * it's queued when we send it. That way we don't sit 089 * around waiting for the client to process it. Only 090 * methods that return 'void' may be buffered.</p> 091 * 092 * @jws:conversation phase="continue" 093 * @common:message-buffer enable="true" 094 */ 095 void onProgressNotify(String progressMsg); 096 097 /** 098 * <p>We call this method to deliver the final credit 099 * report once we're completely done (both external 100 * services have completed).</p> 101 * 102 * <p>We define the format of the message this 103 * callback contains by using a custom XQuery map. 104 * An XQuery map is like an XML map, except that it 105 * uses XQuery expressions to retrieve values that should 106 * be inserted into the message. </p> 107 * 108 * @jws:conversation phase="finish" 109 * 110 * @common:message-buffer enable="true" 111 * @jws:parameter-xml schema-element="ns0:creditReport" xquery:: 112 * declare namespace ns0="http://workshop.bea.com/CreditReport" 113 * declare namespace ns1="http://openuri.org/bea/samples/workshop/creditReport" 114 115 * <ns1:creditReport> 116 * <ns1:bankReport>{data($input//ns0:bank)}</ns1:bankReport> 117 * <ns1:taxReport>{data($input//ns0:tax)}</ns1:taxReport> 118 * </ns1:creditReport> 119 * :: 120 */ 121 void onReportDone(ReportResult resultMsg); 122 } 123 124 /** 125 * <p>Request a credit report from our service.</p> 126 * 127 * <p>Since it may take some time for us to complete 128 * the report (we have to wait until both of our 129 * requests to external services complete), this 130 * methods has no return value. We will return the 131 * result to the client at a later time via the 132 * onReportDone() callback, above.</p> 133 * 134 * <p>We start a conversation so that per-client 135 * information will be persisted and correlated. 136 * There may be several clients using this service 137 * simultaneously. Conversations keep track of 138 * data and message traffic on a per-client basis 139 * automatically.</p> 140 * 141 * <p>We add the @common:message-buffer tag so the client 142 * doesn't syncrhonously wait for a return from 143 * this request.</p> 144 * 145 * @common:operation 146 * @jws:conversation phase="start" 147 * @common:message-buffer enable="true" 148 */ 149 public void requestReport(String ssn) 150 { 151 // Request information from the bank 152 bankControl.startCustomerAnalysis(ssn); 153 154 // Request information from the IRS 155 irsControl.requestTaxReport(ssn); 156 157 /* 158 * Both of the external services will return 159 * their responses to us via callbacks that 160 * we will recieve via the handlers 161 * bank_onDeliverAnalysis and irs_onDeliverTaxReport, 162 * below. So we're done initiating the request. 163 */ 164 return; 165 } 166 167 /** 168 * <p>Request the current status of the request.</p> 169 * 170 * <p>For our impatient customers, we can give them 171 * partial results whenever they ask for them.</p> 172 * 173 * <p>Since this only makes sense after a request 174 * is initiated (ie., a conversation is started), 175 * this is a continue method that runs 176 * in the context of an existing conversation.</p> 177 * 178 * <p>The current result is delivered as an XML 179 * message with its format controlled by 180 * an XQuery map.</p> 181 * 182 * @common:operation 183 * @jws:conversation phase="continue" 184 * @jws:return-xml schema-element="ns0:creditReportReturn" xquery:: 185 * declare namespace ns0="http://workshop.bea.com/CreditReport" 186 * declare namespace ns1="http://openuri.org/bea/samples/workshop/creditReport" 187 188 * <ns1:creditReportReturn> 189 * <ns1:bankReport>{data($input//ns0:bank)}</ns1:bankReport> 190 * <ns1:taxReport>{data($input//ns0:tax)}</ns1:taxReport> 191 * </ns1:creditReportReturn> 192 * :: 193 */ 194 public ReportResult getCurrentStatus() 195 { 196 /* 197 * Call an internal helper method to construct 198 * an intermediate result. 199 */ 200 return assembleResult(); 201 } 202 203 /** 204 * <p>Cancel the credit report request.</p> 205 * 206 * <p>This is marked as a finish method so that the 207 * conversation is automatically ended when we 208 * finish processing this message.</p> 209 * 210 * <p>We've declared this as a buffered method so the 211 * client doesn't sit around waiting for a return.</p> 212 * 213 * @common:operation 214 * @jws:conversation phase="finish" 215 * @common:message-buffer enable="true" 216 */ 217 public void cancelReport() 218 { 219 /* 220 * If we haven't heard form the bank, cancel 221 * the request to the bank. 222 */ 223 if (bankReport == null) 224 { 225 bankControl.cancelAnalysis(); 226 } 227 228 /* 229 * If we haven't heard form the IRS, cancel 230 * the request to the IRS. 231 */ 232 if (taxReport == null) 233 { 234 irsControl.cancelReport(); 235 } 236 } 237 238 /** 239 * <p>Handler for the onDeliverAnalysis callback of the Bank.jws 240 * web service.</p> 241 * 242 * <p>The name of the handler is always the variable name of the 243 * service control ('bank' in this case), followed by an 244 * underscore and the name of the callback.</p> 245 */ 246 public void bankControl_onDeliverAnalysis(String analysisResult) 247 { 248 /* 249 * Store the bank result in persistent storage. 250 */ 251 bankReport = analysisResult; 252 253 /* 254 * Notify the client that we have recieved results 255 * from the bank. 256 */ 257 callback.onProgressNotify("Bank Report Received"); 258 259 /* 260 * Check to see if all results have been received. 261 * If so, checkIfDone will send the completed 262 * results. 263 */ 264 checkIfDone(); 265 } 266 267 /** 268 * <p>Handler for the onDeliverTaxReport callback of the IRS.jws 269 * web service.</p> 270 * 271 * <p>The name of the handler is always the variable name of the 272 * service control ('irs' in this case), followed by an 273 * underscore and the name of the callback.</p> 274 */ 275 public void irsControl_onDeliverTaxReport(String report) 276 { 277 /* 278 * Store the IRS result in persistent storage. 279 */ 280 taxReport = report; 281 282 /* 283 * Notify the client that we have recieved results 284 * from the IRS. 285 */ 286 callback.onProgressNotify("Tax Report Received"); 287 288 /* 289 * Check to see if all results have been received. 290 * If so, checkIfDone will send the completed 291 * results. 292 */ 293 checkIfDone(); 294 } 295 296 /** 297 * A private helper that builds our simple credit report, 298 * using the current (possibly incomplete) results. 299 */ 300 private ReportResult assembleResult() 301 { 302 ReportResult result = new ReportResult(); 303 304 /* 305 * Java includes the ?: construct as a shorthand way of 306 * coding if-then-else. The statement takes the form: 307 * 308 * value = condition ? value-if-true : value-if-false 309 * 310 * If condition evaluates to true, the value-if-true 311 * expression is evaluated and the result is assigned 312 * to value. If condition evaluates to false, the 313 * value-if-false expression is evaluated and the 314 * result is assigned to value. 315 */ 316 result.bank = (bankReport == null) ? "Not Received" : bankReport; 317 result.tax = (taxReport == null) ? "Not Received" : taxReport; 318 319 return result; 320 } 321 322 /** 323 * A private helper that may call "callback.onReportDone" if 324 * we're actually done. 325 */ 326 private void checkIfDone() 327 { 328 /* 329 * If all results are back from external services... 330 */ 331 if (bankReport != null && taxReport != null) 332 { 333 /* 334 * ... call the client with the completed results. 335 */ 336 callback.onReportDone(assembleResult()); 337 } 338 return; 339 } 340 }`