1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Axis User's Guide</title>
<link href="axis.css" rel=stylesheet type=text/css>
</head>
<body >
<center>
<h1>
<img SRC="images/axis.jpg" height=96 width=176></h1></center>
<h1>Axis User's Guide</h1>
<i>1.4 Version</i>
<br><i>Feedback: <a href="mailto:axis-dev@ws.apache.org">axis-dev@ws.apache.org</a></i>
<h3>
Table of Contents</h3>
<ul>
<li> <a href="#Introduction">Introduction</a></li>
<li> <a href="#Installation">Installing Axis</a></li>
<li> <a href="#ConsumingServices">Consuming Web Services with Axis</a></li>
<li> <a href="#PublishingServices">Publishing Web Services with Axis</a></li>
<li> <a href="#DataMapping">XML <-> Java Data Mapping in Axis</a></li>
<li> <a href="#WSDL">Using WSDL with Axis</a></li>
<ul>
<li> <a href="#WSDL: Obtaining WSDL for deployed services">?WSDL: Obtaining
WSDL for deployed services</a></li>
<li> <a href="#WSDL2Java: Building stubs, skeletons, and data">WSDL2Java:
Building stubs, skeletons, and data</a></li>
<li> <a href="#Java2WSDL: Building WSDL from Java">Java2WSDL: Building
WSDL from Java</a></li>
</ul>
<li> <a href="#published interfaces">Published Interfaces</a></li>
<li> <a href="#newbie">Newbie Tips: Finding Your Way Around</a></li>
<li> <a href="#tcpmon">Appendix : Using TCPMon</a></li>
<li> <a href="#soapmon">Appendix : Using SOAP Monitor</a></li>
<li> <a href="#Glossary">Glossary</a></li>
</ul>
<h2>
<a NAME="Introduction"></a>Introduction</h2>
Welcome to Axis, the third generation of Apache SOAP!
<h3>
What is SOAP?</h3>
<p>
SOAP is an XML<i>-</i>based communication protocol and encoding format for inter-application
communication. Originally conceived by Microsoft and Userland software, it has
evolved through several generations; the current spec is version,
<a href="http://w3.org/TR/soap">SOAP 1.2</a>, though version1.1 is more
widespread. The W3C's <a href="http://www.w3.org/2000/xp/Group/">XML
Protocol working group</a> is in charge of the specification.
</p>
<p>SOAP is widely viewed as the backbone to a new generation of cross-platform
cross-language distributed computing applications, termed Web Services.
</p>
<h3>
What is Axis?</h3>
Axis is essentially a <i>SOAP engine</i> -- a framework for
constructing SOAP processors such as
clients, servers, gateways, etc.
The current version of Axis is written in Java, but
a C++ implementation of the client side of Axis is being developed.
<p>
But Axis isn't just a SOAP engine -- it also includes:
<ul>
<li> a simple stand-alone server,
<li> a server which plugs into servlet engines such as Tomcat,
<li> extensive support for the <i>Web Service Description Language (WSDL)</i>,
<li> emitter tooling that generates Java classes from WSDL.
<li> some sample programs, and
<li> a tool for monitoring TCP/IP packets.
</ul>
<p>
Axis is the third generation of Apache SOAP (which began at IBM as "SOAP4J").
In late 2000, the committers of Apache SOAP v2 began discussing
how to make the engine much more flexible, configurable, and able to handle
both SOAP and the upcoming XML Protocol specification from the W3C.
<p>After a little while, it became clear that a ground-up rearchitecture
was required. Several of the v2 committers proposed very similar designs,
all based around configurable "chains" of message "handlers" which would
implement small bits of functionality in a very flexible and composable
manner.
<p>After months of continued discussion and coding
effort in this direction, Axis now delivers the following key features:
<ul>
<li> <b>Speed.</b> Axis uses SAX (event-based) parsing to acheive significantly
greater speed than earlier versions of Apache SOAP.</li>
<li> <b>Flexibility.</b> The Axis architecture gives the developer complete
freedom to insert extensions into the engine for custom header processing,
system management, or anything else you can imagine.</li>
<li> <b>Stability.</b> Axis defines a set of <a href="#published interfaces">published
interfaces</a> which change relatively slowly compared to the rest of Axis.</li>
<li> <b>Component-oriented deployment.</b> You can easily define reusable networks
of Handlers to implement common patterns of processing for your applications,
or to distribute to partners.</li>
<li> <b>Transport framework.</b> We have a clean and simple abstraction for
designing transports (i.e., senders and listeners for SOAP over various protocols
such as SMTP, FTP, message-oriented middleware, etc), and the core of the
engine is completely transport-independent.</li>
<li><b>WSDL support.</b> Axis supports the <a href="http://www.w3.org/TR/wsdl">Web
Service Description Language</a>, version 1.1, which allows you to easily
build stubs to access remote services, and also to automatically export machine-readable
descriptions of your deployed services from Axis.</li>
</ul>
<p>
We hope you enjoy using Axis. Please note that this is an open-source effort
- if you feel the code could use some new features or fixes, please get
involved and lend a hand! The Axis developer community welcomes your
participation. And in case you're wondering what <i>Axis</i> stands for,
it's <b>A</b>pache E<b>X</b>tensible <b>I</b>nteraction <b>S</b>ystem -
a fancy way of implying it's a very configurable SOAP engine.
<h4>
<b>Let us know what you think!</b></h4>
Please send feedback about the package to "<a href="mailto:axis-user@ws.apache.org">axis-user@ws.apache.org</a>".
Also, Axis is registered in <a href="http://nagoya.apache.org/bugzilla">bugzilla</a>,
the Apache bug tracking and feature-request database.
<h3>
What's in this release?</h3>
This release includes the following features:
<ul>
<li> SOAP 1.1/1.2 compliant engine</li>
<li> Flexible configuration / deployment system</li>
<li> Support for "drop-in" deployment of SOAP services (JWS)</li>
<li> Support for all basic types, and a type mapping system for defining new
serializers/deserializers</li>
<li> Automatic serialization/deserialization of Java Beans, including customizable
mapping of fields to XML elements/attributes</li>
<li> Automatic two-way conversions between Java Collections and SOAP Arrays</li>
<li> Providers for RPC and message based SOAP services</li>
<li> Automatic WSDL generation from deployed services</li>
<li> WSDL2Java tool for building Java proxies and skeletons from WSDL documents</li>
<li> Java2WSDL tool for building WSDL from Java classes.</li>
<li> Preliminary security extensions, which can integrate with Servlet 2.2 security/roles</li>
<li>Support for session-oriented services, via HTTP cookies or transport-independent
SOAP headers</li>
<li>Preliminary support for the <b>SOAP with Attachments</b> specification</li>
<li> An EJB provider for accessing EJB's as Web Services</li>
<li> HTTP servlet-based transport</li>
<li> JMS based transport</li>
<li> Standalone version of the server (with HTTP support)</li>
<li> Examples, including a client and server for the SoapBuilders community
interoperability tests and experimental TCP, JMS, and file-based transports.</li>
</ul>
<h3> What's still to do?</h3>
<p>Please click for <a href="to-do.html">a list of what we think needs doing</a>
- and please consider helping out if you're interested & able!</p>
<h2>
<a NAME="Installation"></a>Installing Axis and Using this Guide</h2>
See the <a href="install.html">Axis Installation Guide</a>
for instructions on installing Axis as a web application on your J2EE server.
<p>Before running the examples in this guide, you'll need to make sure
that your CLASSPATH includes
(Note: If you build Axis from a CVS checkout,
these will be in xml-axis/java/build/lib instead of axis-1_2/lib):
<ul>
<li>axis-1_2/lib/axis.jar</li>
<li>axis-1_2/lib/jaxrpc.jar</li>
<li>axis-1_2/lib/saaj.jar</li>
<li>axis-1_2/lib/commons-logging.jar</li>
<li>axis-1_2/lib/commons-discovery.jar</li>
<li>axis-1_2/lib/wsdl4j.jar</li>
<li>axis-1_2/ <i><font color="#9966FF">(for the sample code)</font></i></li>
<li>A JAXP-1.1 compliant XML parser such as Xerces or Crimson. We recommend
<A href="http://xml.apache.org/xerces2-j/">Xerces</A>, as it is the one
that the product has been tested against.</li>
</ul>
<h2>
<a NAME="ConsumingServices"></a>Consuming Web Services with Axis</h2>
<h3>
Basics - Getting Started</h3>
Let's take a look at an example Web Service client that will call the <b>echoString</b>
method on the public Axis server at Apache.
<pre class="example">1 import org.apache.axis.client.Call;
2 import org.apache.axis.client.Service;
3 import javax.xml.namespace.QName;
4
5 public class TestClient {
6 public static void main(String [] args) {
7 try {
8 String endpoint =
9 "http://nagoya.apache.org:5049/axis/services/echo";
10
11 Service service = new Service();
12 Call call = (Call) service.createCall();
13
14 call.setTargetEndpointAddress( new java.net.URL(endpoint) );
15 call.setOperationName(new QName("<font color="#009933">http://soapinterop.org/</font>", "<font color="#993333">echoString</font>"));
16
17 String ret = (String) call.invoke( new Object[] { "<font color="#CC00CC">Hello!</font>" } );
18
19 System.out.println("Sent 'Hello!', got '" + ret + "'");
20 } catch (Exception e) {
21 System.err.println(e.toString());
22 }
23 }
24 }</pre>
(You'll find this file in <a href="../samples/userguide/example1/TestClient.java">samples/userguide/example1/TestClient.java</a>)
<p>Assuming you have a network connection active, this program can be run
as follows:
<pre class="example">% java samples.userguide.example1.TestClient
Sent 'Hello!', got 'Hello!'
%</pre>
So what's happening here? On lines 11 and 12 we create new Service and
Call objects. These are the standard JAX-RPC objects that are used to store
metadata about the service to invoke. On line 14, we set up our endpoint
URL - this is the destination for our SOAP message. On line 15 we define
the operation (method) name of the Web Service. And on line 17 we actually invoke
the desired service, passing in an array of parameters - in this case just
one String.
<p>You can see what happens to the arguments by looking at the SOAP request that
goes out on the wire (look at the colored sections, and notice they match the
values in the call above):
<pre class="xml"><?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:<b><font color="#993333">echoString</font></b> xmlns:ns1="<b><font color="#009933">http://soapinterop.org/</font></b>">
<arg0 xsi:type="xsd:string"><b><font color="#CC00CC">Hello!</font></b></arg0>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope></pre>
<p>The String argument is automatically serialized into XML, and the server
responds with an identical String, which we deserialize and print.</p>
<p><i>Note: To actually watch the XML flowing back and forth between a
SOAP client and server, you can use the included <a href="#tcpmon">tcpmon</a> tool or <a href="#soapmon">SOAP monitor</a> tool. See the appendix
for an overview.</i></p>
<h3>Naming Parameters</h3>
In the above example, you can see that Axis automatically names the XML-encoded
arguments in the SOAP message "arg0", "arg1", etc. (In this case there's just
"arg0") If you want to change this, it's easy! Before calling <tt>invoke()</tt>
you need to call <tt>addParameter</tt> for each parameter and <tt>setReturnType</tt> for the return, like so:
<pre class="example"> call.addParameter("testParam",
org.apache.axis.Constants.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);
call.setReturnType(org.apache.axis.Constants.XSD_STRING); </pre>
This will assign the name <b>testParam</b> to the 1st (and only) parameter
on the invoke call. This will also define the type of the parameter (<tt>org.apache.axis.Constants.XSD_STRING</tt>)
and whether it is an input, output or inout parameter - in this case its
an input parameter. Now when you run the program you'll get a message that
looks like this:
<pre class="xml"><?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoString xmlns:ns1="http://soapinterop.org/">
<<font color="#CC00CC">testParam</font> xsi:type="xsd:string">Hello!</<font color="#CC00CC">testParam</font>>
</ns1:echoString>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope></pre>
Note that the param is now named "testParam" as expected.
<h3>Interoperating with "untyped" servers</h3>
In the above examples, we've been casting the return type of invoke(),
which is Object, to the appropriate "real" type - for instance, we know
that the echoString method returns a String, so we expect to get one back
from client.invoke(). Let's take a moment and investigate how this happens,
which sheds light on a potential problem (to which, of course, we have
a solution - so don't fret :)).
<p>Here's what a typical response might look like to the echoString method: </p>
<pre class="xml"><?xml version="1.0" encoding="UTF-8"?><br> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
<result <font color="#FF0000">xsi:type="xsd:string"</font>>Hello!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope></pre>
<p>Take a look at the section which we've highlighted in <font color="#FF0000">red</font>
- that attribute is a schema <b>type declaration</b>, which Axis uses to figure
out that the contents of that element are, in this case, deserializable into a
Java String object. Many toolkits put this kind of explicit typing information
in the XML to make the message "self-describing". On the other hand, some toolkits
return responses that look like this: </p>
<pre class="xml"><?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
<result>Hello, I'm a string!</result>
</ns1:echoStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope></pre>
<p>There's no type in the message, so how do we know what Java object we should
deserialize the <result> element into? The answer is <b>metadata</b>
- data about data. In this case, we need a <b>description</b> of the service
that tells us what to expect as the return type. Here's how to do it on
the client side in Axis:</p>
<pre class="example"> call.setReturnType( org.apache.axis.Constants.XSD_STRING );</pre>
<p>This method will tell the Axis client that if the return element is not typed
then it should act as if the return value has an xsi:type attribute set to the
predefined SOAP String type. (You can see an example of this in action in the
interop echo-test client - samples/echo/TestClient.java.) </p>
<p>There is also a similar method which allows you to specify the Java class of
the expected return type:</p>
<pre class="example">call.setReturnClass(String.class);</pre>
<p>OK - so now you know the basics of accessing SOAP services as a client.
But how do you publish your own services?
<h2>
<a NAME="PublishingServices"></a>Publishing Web Services with Axis</h2>
Let's say we have a simple class like the following:
<pre class="example">public class Calculator {
public int add(int i1, int i2)
{
return i1 + i2;
}
public int subtract(int i1, int i2)
{
return i1 - i2;
}
}</pre>
(You'll find this very class in <a href="../samples/userguide/example2/Calculator.java">samples/userguide/example2/Calculator.java</a>.)
<p>How do we go about making this class available via SOAP? There are a
couple of answers to that question, but we'll start with the easiest way
Axis provides to do this, which takes almost no effort at all!
<h3>
JWS (Java Web Service) Files - Instant Deployment</h3>
OK, here's step 1 : copy the above .java file into your webapp directory,
and rename it "Calculator.jws". So you might do something like this:
<pre>% copy Calculator.java <i><font color="#0000FF"><your-webapp-root></font></i>/axis/Calculator.jws</pre>
Now for step 2... hm, wait a minute. You're done! You should now be able
to access the service at the following URL (assuming your Axis web application
is on port 8080):
<p><a href="http://localhost:8080/axis/Calculator.jws">http://localhost:8080/axis/Calculator.jws</a>
<p>Axis automatically locates the file, compiles the class, and converts
SOAP calls correctly into Java invocations of your service class. Try it
out - there's a calculator client in samples/userguide/example2/CalcClient.java,
which you can use like this:
<pre class="example">% java samples.userguide.example2.CalcClient -p8080 add 2 5
Got result : 7
% java samples.userguide.example2.CalcClient -p8080 subtract 10 9
Got result : 1
%</pre>
(Note that you may need to replace the "-p8080" with whatever port your
J2EE server is running on)
<p>
<i><b>Important:</b></i> JWS web services are intended for simple web services.
You cannot use packages in the pages, and as the code is compiled at run
time you can not find out about errors until after deployment.
Production quality web services should use Java classes with custom
deployment.
<h3>
Custom Deployment - Introducing WSDD</h3>
JWS files are great quick ways to get your classes out there as Web Services,
but they're not always the best choice. For one thing, you need the source code
- there might be times when you want to expose a pre-existing class on your system
without source. Also, the amount of configuration you can do as to how the service
gets accessed is pretty limited - you can't specify custom type mappings, or control
which Handlers get invoked when people are using your service. <i>(Note for the
future : the Axis team, and the Java SOAP community at large, are thinking about
ways to be able to embed this sort of metadata into your source files if desired
- stay tuned!)</i>
<h4>
<a NAME="descriptors"></a>Deploying via descriptors</h4>
<p>To really use the flexibility available to you in Axis, you should get
familiar with the Axis <b>Web Service Deployment Descriptor (WSDD)</b>
format. A deployment descriptor contains a bunch of things you want to
"deploy" into Axis - i.e. make available to the Axis engine. The most common
thing to deploy is a Web Service, so let's start by taking a look at a
deployment descriptor for a basic service (this file is <a href="../samples/userguide/example3/deploy.wsdd">samples/userguide/example3/deploy.wsdd</a>):</p>
<pre class="example"><deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="MyService" provider="java:RPC">
<parameter name="className" value="samples.userguide.example3.MyService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment></pre>
Pretty simple, really - the outermost element tells the engine that this is a
WSDD deployment, and defines the "java" namespace. Then the service element actually
defines the service for us. A service is a <b>targeted chain</b> (see the <a href="architecture-guide.html">Architecture
Guide</a>), which means it may have any/all of: a request flow, a pivot Handler
(which for a service is called a "provider"), and a response flow. In this case,
our provider is "java:RPC", which is built into Axis, and indicates a Java RPC
service. The actual class which handles this is <b>org.apache.axis.providers.java.RPCProvider</b>.
We'll go into more detail later on the different styles of services and their
providers.
<p>We need to tell the RPCProvider that it should instantiate and call the correct
class (e.g. samples.userguide.example3.MyService), and we do so by including
<parameter> tags, giving the service one parameter to configure the class
name, and another to tell the engine that any public method on that class may
be called via SOAP (that's what the "*" means; we could also have restricted
the SOAP-accessible methods by using a space or comma separated list of available
method names).
<h4>Advanced WSDD - specifying more options</h4>
<p>WSDD descriptors can also contain other information about services, and also
other pieces of Axis called "Handlers" which we'll cover in a later
section.
<h5>Scoped Services</h5>
<p>Axis supports scoping service objects (the actual Java objects which implement
your methods) three ways. "Request" scope, the default, will create
a new object each time a SOAP request comes in for your service. "Application"
scope will create a singleton shared object to service <b>all</b> requests.
"Session" scope will create a new object for each session-enabled
client who accesses your service. To specify the scope option, you add a <parameter>
to your service like this (where "<i><font color="#FF0000">value</font></i>"
is request, session, or application):</p>
<pre class="xml"><service name="MyService"...>
<parameter name="scope" value="<font color="#FF0000"><i>value</i></font>"/>
...
</service></pre>
<h4>Using the AdminClient</h4>
Once we have this file, we need to send it to an Axis server in order to actually
deploy the described service. We do this with the AdminClient, or the "org.apache.axis.client.AdminClient"
class. If you have deployed Axis on a server other than Tomcat, you may need to
use the -p <em><port></em> argument. The default port is 8080.
A typical invocation of the AdminClient looks like this:
<pre class="example">% java org.apache.axis.client.AdminClient deploy.wsdd
<Admin>Done processing</Admin></pre>
This command has now made our service accessible via SOAP. Check it out
by running the Client class - it should look like this:
<pre class="example">% java samples.userguide.example3.Client -lhttp://localhost:8080/axis/services/MyService "test me!"
You typed : test me!
%</pre>
If you want to prove to yourself that the deployment really worked, try
undeploying the service and calling it again. There's an "undeploy.wsdd"
file in the example3/ directory which you can use just as you did the deploy.wsdd
file above. Run the AdminClient on that file, then try the service
Client again and see what happens.
<p>You can also use the AdminClient to get a listing of all the deployed
components in the server:
<pre class="example">% java org.apache.axis.client.AdminClient list
<big XML document returned here></pre>
In there you'll see services, handlers, transports, etc. Note that this
listing is an exact copy of the server's "server-config.wsdd" file, which
we'll talk about in more detail a little later.
<h4>
More deployment - Handlers and Chains</h4>
Now let's start to explore some of the more powerful features of the Axis
engine. Let's say you want to track how many times your service has been
called. We've included a sample handler in the samples/log directory to
do just this. To use a handler class like this, you first need to deploy
the Handler itself, and then use the name that you give it in deploying
a service. Here's a sample deploy.wsdd file (this is example 4 in samples/userguide):
<pre class="example"><deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- define the logging handler configuration -->
<handler name="track" type="java:samples.userguide.example4.LogHandler">
<parameter name="filename" value="MyService.log"/>
</handler>
<!-- define the service, using the log handler we just defined -->
<service name="LogTestService"<b> </b>provider="java:RPC">
<requestFlow>
<handler type="track"/>
</requestFlow>
<parameter name="className" value="samples.userguide.example4.Service"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment></pre>
<p>The first section defines a Handler called "track" that is implemented
by the class samples.userguide.example4.LogHandler. We give this Handler
an option to let it know which file to write its messages into.
<p>Then we define a service, LogTestService, which is an RPC service just
like we saw above in our first example. The difference is the <requestFlow>
element inside the <service> - this indicates a set of Handlers that
should be invoked when the service is invoked, before the provider. By
inserting a reference to "track", we ensure that the message will be logged
each time this service is invoked.
<h4>
Remote Administration</h4>
Note that by default, the Axis server is configured to only accept administration
requests from the machine on which it resides - if you wish to enable remote
administration, you must set the "enableRemoteAdmin" property of the AdminService
to <b>true</b>. To do this, find the "server-config.wsdd" file in your
webapp's WEB-INF directory. In it, you'll see a deployment for the AdminService.
Add an option as follows:
<pre class="xml"><service name="AdminService" provider="java:MSG">
<parameter name="className" value="org.apache.axis.util.Admin"/>
<parameter name="allowedMethods" value="*"/>
<b><parameter name="enableRemoteAdmin" value="true"/>
</b></service></pre>
<p><b>WARNING: enabling remote administration may give unauthorized parties
access to your machine. If you do this, please make sure to add security
to your configuration!</b>
<h3>Service Styles - RPC, Document, Wrapped, and Message</h3>
<p>There are four "styles" of service in Axis. <b>RPC</b> services
use the SOAP RPC conventions, and also the SOAP "section 5" encoding.
<b>Document</b> services do not use any encoding (so in particular, you won't
see multiref object serialization or SOAP-style arrays on the wire) but DO still
do XML<->Java databinding. <b>Wrapped</b> services are just like document
services, except that rather than binding the entire SOAP body into one big
structure, they "unwrap" it into individual parameters. <b>Message</b>
services receive and return arbitrary XML in the SOAP Envelope without any type
mapping / data binding. If you want to work with the raw XML of the incoming
and outgoing SOAP Envelopes, write a message service.</p>
<h4>RPC services</h4>
RPC services are the default in Axis. They are what you get when you deploy services
with <service ... provider="java:RPC"> or <service ... style="RPC">.
RPC services follow the SOAP RPC and encoding rules, which means that the XML
for an RPC service will look like the "echoString" example above - each
RPC invocation is modeled as an outer element which matches the operation name,
containing inner elements each of which maps to a parameter of the operation.
Axis will deserialize XML into Java objects which can be fed to your service,
and will serialize the returned Java object(s) from your service back into XML.
Since RPC services default to the soap section 5 encoding rules, objects will
be encoded via "multi-ref" serialization, which allows object graphs
to be encoded. (See the SOAP spec for more on multi-ref serialization.)
<h4>Document / Wrapped services </h4>
<p>Document services and wrapped services are similar in that neither uses the
SOAP encoding for data; it's just plain old XML schema. In both cases, however,
Axis still "binds" Java representations to the XML (see the <a href="#DataMapping">databinding</a>
section for more), so you end up dealing with Java objects, not directly with
XML constructs.</p>
<p>A good place to start in describing the difference between document and wrapped
services is with a sample SOAP message containing a purchase order:</p>
<pre class="xml"><soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<soap:Body>
<myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
<item>SK001</item>
<quantity>1</quantity>
<description>Sushi Knife</description>
</myNS:PurchaseOrder>
</soap:Body>
</soap:Envelope>
</pre>
<p>The relevant schema for the PurchaseOrder looks like this:</p>
<pre class="xml"><schema targetNamespace="http://commerce.com/PO">
<complexType name="POType">
<sequence>
<element name="item" type="xsd:string"/>
<element name="quantity" type="xsd:int"/>
<element name="description" type="xsd:string"/>
</sequence>
</complexType>
<element name="PurchaseOrder" type="POType"/>
</deployment></pre>
<p>For a <b>document</b> style service, this would map to a method like this:</p>
<p class="example">public void method(PurchaseOrder po)</p>
<p>In other words, the ENTIRE <PurchaseOrder> element would be handed to
your method as a single bean with three fields inside it. On the other hand,
for a <b>wrapped</b> style service, it would map to a method like this:</p>
<p class="example">public void purchaseOrder(String item, int quantity, String
description)</p>
<p>Note that in the "wrapped" case, the <PurchaseOrder> element
is a "wrapper" (hence the name) which only serves to indicate the
correct operation. The arguments to our method are what we find when we "unwrap"
the outer element and take each of the inner ones as a parameter.</p>
<p>The document or wrapped style is indicated in WSDD as follows:</p>
<p><span class="example"><service ... style="document"></span>
for document style<br>
<span class="example"><service ... style="wrapped"></span> for
wrapped style</p>
<p>In most cases you won't need to worry about document or wrapped services if
you are starting from a WSDL document (<a href="#WSDL">see below</a>).</p>
<h4>Message services</h4>
<p>Finally, we arrive at "Message" style services, which should be used
when you want Axis to step back and let your code at the actual XML instead
of turning it into Java objects. There are four valid signatures for your message-style
service methods:</p>
<p><code>public Element [] method(Element [] bodies);</code><code><br>
public SOAPBodyElement [] method (SOAPBodyElement [] bodies);</code><code><br>
public Document method(Document body);<br>
public void method(SOAPEnvelope req, SOAPEnvelope resp);</code> </p>
<p>The first two will pass your method arrays of either DOM Elements or SOAPBodyElements
- the arrays will contain one element for each XML element inside the <soap:body>
in the envelope.</p>
<p>The third signature will pass you a DOM Document representing the <soap:body>,
and expects the same in return.</p>
<p>The fourth signature passes you two SOAPEnvelope objects representing the request
and response messages. This is the signature to use if you need to look at or
modify headers in your service method. Whatever you put into the response envelope
will automatically be sent back to the caller when you return. Note that the
response envelope may already contain headers which have been inserted by other
Handlers.</p>
<p><b>Message Example</b></p>
<p>A sample message service can be found in <a href="../samples/message/MessageService.java">samples/message/MessageService.java</a>.
The service class, <code>MessageService</code>, has one public method, <code>echoElements</code>,
which matches the first of the three method signatures above:</p>
<pre class="example">public Element[] echoElements(Element [] elems) </pre>
<p>The <code>MsgProvider</code> handler calls the method with an array<code></code>
of <code>org.w3c.dom.Element</code> objects that correspond to the immediate
children of the incoming message's SOAP Body. Often, this array will contain
a single Element (perhaps the root element of some XML document conforming to
some agreed-upon schema), but the SOAP Body can handle any number of children.
The method returns an <code>Element[]</code> array to be returned in the SOAP
body of the response message.</p>
<p>Message services must be deployed with a WSDD file. Here is the full WSDD for
the <code>MessageService</code> class:</p>
<pre class="XML">
<deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
<service name="MessageService" <font color="#FF0000">style="message"</font>>
<parameter name="className" value="samples.message.MessageService"/>
<parameter name="allowedMethods" value="echoElements"/>
</service><br></deployment></pre>
<p>Note that the "style" attribute is different from the RPC deployment
example. The "message" style tells Axis that this service is to be
handled by <code>org.apache.axis.providers.java.MsgProvider</code> rather than
<code>org.apache.axis.providers.java.RPCProvider</code>. </p>
<p>You can test this service by deploying it, then running samples.message.TestMsg
(look at the source to see what the test driver does).</p>
<h2><a NAME="DataMapping"></a>XML <-> Java Data Mapping in Axis</h2>
<h3>How your Java types map to SOAP/XML types</h3>
Interoperability, <i>interop</i>, is an ongoing challenge
between SOAP implementations. If you want your service to work with other platforms
and implementations, you do need to understand the issues. There are some
<a href="reading.html#interop">external articles</a> on the subject that act
as a good starting place.
The basic mapping between Java types and WSDL/XSD/SOAP in Axis is determined by
the JAX-RPC specification. Read chapters 4 and 5 of the
<a href="http://java.sun.com/xml/jaxrpc/">
specification</a> to fully understand how things are converted. Here are
some of the salient points.
<h4>Standard mappings from WSDL to Java</h4>
<table>
<tr><td>xsd:base64Binary </td><td><tt>byte[]</tt></td></tr>
<tr><td>xsd:boolean </td><td><tt>boolean</tt></td></tr>
<tr><td>xsd:byte </td><td><tt>byte</tt></td></tr>
<tr><td>xsd:dateTime </td><td><tt>java.util.Calendar</tt></td></tr>
<tr><td>xsd:decimal </td><td><tt>java.math.BigDecimal</tt></td></tr>
<tr><td>xsd:double </td><td><tt>double</tt></td></tr>
<tr><td>xsd:float </td><td><tt>float</tt></td></tr>
<tr><td>xsd:hexBinary </td><td><tt>byte[]</tt></td></tr>
<tr><td>xsd:int</td><td><tt> int</tt></td></tr>
<tr><td>xsd:integer</td><td><tt>java.math.BigInteger</tt></td></tr>
<tr><td>xsd:long </td><td><tt>long</tt></td></tr>
<tr><td>xsd:QName </td><td><tt>javax.xml.namespace.QName</tt></td></tr>
<tr><td>xsd:short </td><td><tt>short</tt></td></tr>
<tr><td>xsd:string</td><td><tt>java.lang.String</tt></td></tr>
</table>
<p> If the WSDL says that an object can be <tt>nillable</tt>, that is the caller
may choose to return a value of <tt>nil</tt>, then the primitive data types
are replaced by their wrapper classes, such as Byte, Double, Boolean, etc.
<h4>SOAP Encoding Datatypes</h4>
<p> Alongside the XSD datatypes are the SOAP 'Section 5' datatypes that are all
nillable, and so only ever map to the wrapper classes. These types exist because
they all support the "ID" and "HREF" attributes, and so
will be used when in an RPC-encoded context to support multi-ref serialization.
<h3>Exceptions</h3>
This is an area which causes plenty of confusion, and indeed, the author
of this section is not entirely sure how everything works, especially
from an interop perspective. This means treat this section as
incomplete and potentially inaccurate. See also section 5.5.5 and
chapter 14 in the JAX-RPC specification
<h4>RemoteExceptions map to SOAP Faults</h4>
If the server method throws a <tt>java.rmi.RemoteException</tt> then
this will be mapped into a SOAP Fault. The <tt>faultcode</tt> of this will contain
the classname of the fault. The recipient is expected to deserialize the
body of the fault against the classname.
<p>
Obviously, if the recipient does not know how to create an instance of
the received fault, this mechanism does not work. Unless you include
information about the exception class in the WSDL description of the
service, or sender and receiver share the implementation,
you can only reliably throw <tt>java.rmi.RemoteException</tt>
instances, rather than subclasses.
<p>
When an implementation in another language receives such an exception,
it should see the name of the class as the faultCode, but still be left
to parse the body of the exception. You need to experiment to find out
what happens there.
<h4>Exceptions are represented as <tt>wsdl:fault</tt> elements</h4>
If a method is marked as throwing an <tt>Exception</tt> that is not
an instance or a subclass of <tt>java.rmi.RemoteException</tt>, then
things are subtly different. The exception is no longer a SOAP Fault, but
described as a <tt>wsdl:fault</tt> in the WSDL of the method.
According to the JAX-RPC specification, your subclass of Exception
must have accessor methods to access all the fields in the object to be
marshalled <i>and</i> a constructor that takes as parameters all the
same fields (i.e, arguments of the same name and type). This is a kind of
immutable variant of a normal <a href="http://java.sun.com/products/javabeans">JavaBean</a>. The fields in the object must be
of the datatypes that can be reliably mapped into WSDL.
<p>
If your exception meets this specification, then the WSDL describing the
method will describe the exception too, enabling callers to create stub
implementations of the exception, regardless of platform.
<p>
Again, to be sure of interoperability, you need to be experiment a bit.
Remember, the calling language may not have the notion of Exceptions, or
at least not be as rigorous as Java in the rules as to how exceptions
must be handled.
<h3>What Axis can send via SOAP with restricted Interoperability</h3>
<h5>Java Collections</h5>
Some of the Collection classes, such as <tt>Hashtable</tt>, do have
serializers, but there is no formal interoperability with other SOAP
implementations, and nothing in the SOAP specifications which covers
complex objects. The most reliable way to send aggregate objects is to
use arrays. In particular, .NET cannot handle them, though many Java SOAP
implementations can marshall and unmarshall hash tables.
<h3>What Axis can not send via SOAP</h3>
<h5>Arbitrary Objects without Pre-Registration</h5>
You cannot send arbitrary Java objects over the wire and expect them to
be understood at the far end. With RMI you can send and receive
<tt>Serializable</tt> Java objects, but that is because you are running
Java at both ends. <b>Axis will only send objects for which there is a
registered Axis serializer.</b> This document shows below how to use
the BeanSerializer to serialize any class that follows the JavaBean
pattern of accessor and mutator. To serve up objects you must either
register your classes with this BeanSerializer, or there must be
serialization support built in to Axis.
<h5>Remote References</h5>
Remote references are neither part of the SOAP specification, nor the JAX-RPC
specification. You cannot return some object reference and expect the
caller to be able to use it as an endpoint for SOAP calls or as a
parameter in other calls. Instead you must use some other reference
mechanism, such as storing them in a <tt>HashMap</tt> with numeric or
string keys that can be passed over the wire.
<h3>Encoding Your Beans - the BeanSerializer</h3>
Axis includes the ability to serialize/deserialize, without writing any
code, arbitrary Java classes which follow the standard <a href="http://java.sun.com/products/javabeans">JavaBean</a> pattern
of get/set accessors. All you need to do is tell Axis which Java classes
map to which XML Schema types. Configuring a bean mapping looks like this:
<pre class="xml"><beanMapping qname="ns:local" xmlns:ns="someNamespace"
languageSpecificType="java:my.java.thingy"/></pre>
The <beanMapping> tag maps a Java class (presumably a bean) to an XML
QName. You'll note that it has two important attributes, <b>qname</b> and
<b>languageSpecificType</b>.
So in this case, we'd be mapping the "my.java.thingy" class to the XML
QName [someNamespace]:[local].
<p>Let's take a look at how this works in practice. Go look at <a href="../samples/userguide/example5/BeanService.java">samples/userguide/example5/BeanService.java</a>. The key
thing to notice is that the argument to the service method is an Order
object. Since Order is not a basic type which Axis understands by default,
trying to run this service without a type mapping will result in a fault.
(If you want to try this for yourself, you can use the bad-deploy.wsdd
file in the example5 directory.) But if we put a beanMapping into our deployment,
all will be well. Here's how to run this example (from the example5 directory):
<pre class="example">% java org.apache.axis.client.AdminClient -llocal:///AdminService deploy.wsdd
<Admin>Done processing</Admin>
% java samples.userguide.example5.Client -llocal://
Hi, Glen Daniels!
You seem to have ordered the following:
1 of item : mp3jukebox
4 of item : 1600mahBattery
If this had been a real order processing system, we'd probably have charged you about now.
%
</pre>
<h3>
When Beans Are Not Enough - Custom Serialization</h3>
Just as JWS deployment is sometimes not flexible enough to meet all needs,
the default bean serialization model isn't robust enough to handle every
case either. At times there will be non-bean Java classes (especially in
the case of pre-existing assets) which you need to map to/from XML, and
there also may be some custom XML schema types which you want to map into
Java in particular ways. Axis gives you the ability to write custom serializers/deserializers,
and some tools to help make your life easier when you do so.
<p><i><font color="#FF0000">TBD - this section will be expanded in a future
version! For now look at the DataSer/DataDeser
classes (in samples/encoding).
Also look at the BeanSerializer, BeanDeserializer, ArraySerializer, ArrayDeserializer and other classes in the org.apache.axis.encoding.ser package.
</font></i>
<h4>
Deploying custom mappings - the <typeMapping> tag</h4>
Now that you've built your serializers and deserializers, you need to tell
Axis which types they should be used for. You do this with a typeMapping
tag in WSDD, which looks like this:
<pre class="xml"><typeMapping qname="ns:local" xmlns:ns="someNamespace"
languageSpecificType="java:my.java.thingy"
serializer="my.java.Serializer"
deserializer="my.java.DeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></pre>
<p>This looks a lot like the <beanMapping> tag we saw earlier, but there
are three extra attributes. One, <b>serializer</b>, is the Java class name
of the Serializer <i>factory</i> which gets the serializer to
be used to marshal an object of the specified Java class
(i.e., my.java.thingy) into XML. Another, <b>deserializer</b>, is
the class name of a Deserializer <i>factory</i> that gets the deserializer
to be used to unmarshall XML into the correct Java class. The final attribute,
the <b>encodingStyle</b>, which is SOAP encoding.
<p>(The <beanMapping> tag is really just shorthand for a <typeMapping> tag
with <tt>serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"</tt>,
<tt>deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"</tt>,
and <tt>encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"</tt>, but clearly it
can save a lot of typing!)
<h4>Deploying array mappings - the <arrayMapping> tag</h4>
Another variation around typeMapping is arrayMapping. The arrayMapping tag is useful
for advanced users wanting to exatly control how their arrays are serialized throught
the wire.
<pre class="xml"><arrayMapping qname="ns:ArrayOfthingy" xmlns:ns="someNamespaceURI"
languageSpecificType="java:my.java.array.thingy[]"
innerType="ns2:thingy" xmlns:ns2="anotherNamespaceURI"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></pre>
No need here to specify a serializer/deserializer couple, the arrayMapping tag
is only about arrays (no List, ...). The added attribute (<i>innerType</i>) is used
to tell Axis what precisely is the item type of the Array.
<h2>
<a NAME="WSDL"></a>Using WSDL with Axis</h2>
The <a href="http://www.w3.org/TR/wsdl">Web Service Description Language</a>
is a specification authored by IBM and Microsoft, and supported by many
other organizations. WSDL serves to describe Web Services in a structured
way. A WSDL description of a service tells us, in a machine-understandable
way, the interface to the service, the data types it uses, and where the
service is located. Please see the spec (follow the link in the first sentence)
for details about WSDL's format and options.
<p>Axis supports WSDL in three ways:
<ol>
<li>
When you deploy a service in Axis, users may then access your service's
URL with a standard web browser and by appending "?WSDL" to the end of
the URL, they will obtain an automatically-generated WSDL document which
describes your service.</li>
<li>
We provide a "WSDL2Java" tool which will build Java proxies and skeletons
for services with WSDL descriptions.</li>
<li>
We provide a "Java2WSDL" tool which will build WSDL from Java classes.</li>
</ol>
<h3>
<a NAME="WSDL: Obtaining WSDL for deployed services"></a>?WSDL: Obtaining
WSDL for deployed services</h3>
When you make a service available using Axis, there is typically a unique
URL associated with that service. For JWS files, that URL is simply the
path to the JWS file itself. For non-JWS services, this is usually the
URL "http://<host>/axis/services/<service-name>".
<p>If you access the service URL in a browser, you'll see a message indicating
that the endpoint is an Axis service, and that you should usually access
it using SOAP. However, if you tack on "?wsdl" to the end of the URL, Axis
will automatically generate a service description for the deployed service,
and return it as XML in your browser (try it!). The resulting description
may be saved or used as input to proxy-generation, described next. You
can give the WSDL-generation URL to your online partners, and they'll be
able to use it to access your service with toolkits like .NET, SOAP::Lite,
or any other software which supports using WSDL.
<p>You can also generate WSDL files from existing Java classes (see <a href="#Java2WSDL: Building WSDL from Java">Java2WSDL:
Building WSDL from Java</a> ).
<br>
<h3><a NAME="WSDL2Java: Building stubs, skeletons, and data"></a>WSDL2Java:
Building stubs, skeletons, and data types from WSDL</h3>
<h4>Client-side bindings</h4>
<p>You'll find the Axis WSDL-to-Java tool in "org.apache.axis.wsdl.WSDL2Java".
The basic invocation form looks like this:</p>
<pre class="example">
% java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL)
</pre>
<p>This will generate only those bindings necessary for the client.
Axis follows the JAX-RPC specification when generating Java client bindings
from WSDL. For this discussion, assume we executed the following:</p>
<pre class="example">
% cd samples/addr
% java org.apache.axis.wsdl.WSDL2Java AddressBook.wsdl
</pre>
<p>The generated files will reside in the directory "AddressFetcher2".
They are put here because that is the target namespace from the WSDL and namespaces map to Java packages.
Namespaces will be discussed in detail later.</p>
<table BORDER COLS=2 WIDTH="100%" >
<tr>
<td><b>WSDL clause</b></td>
<td><b>Java class(es) generated</b></td>
</tr>
<tr>
<td>For each entry in the type section</td>
<td>A java class</td>
</tr>
<tr>
<td></td>
<td>A holder if this type is used as an inout/out parameter</td>
</tr>
<tr>
<td>For each portType</td>
<td>A java interface</td>
</tr>
<tr>
<td>For each binding</td>
<td>A stub class</td>
</tr>
<tr>
<td>For each service</td>
<td>A service interface</td>
</tr>
<tr>
<td></td>
<td>A service implementation (the locator)</td>
</tr>
</table>
There is an <a href="ant/axis-wsdl2java.html">Ant Task</a> to integrate this
action with an Ant based build process.
<h4>Types</h4>
<p>The Java class generated from a WSDL type will be named from the WSDL type.
This class will typically, though not always, be a bean. For example,
given the WSDL (the WSDL used throughout the WSDL2Java discussion is from
the <a href="../samples/addr/AddressBook.wsdl">Address Book sample</a>):</p>
<pre class="example">
<xsd:complexType name="phone">
<xsd:all>
<xsd:element name="areaCode" type="xsd:int"/>
<xsd:element name="exchange" type="xsd:string"/>
<xsd:element name="number" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
</pre>
<p>WSDL2Java will generate:
<pre class="example">
public class Phone implements java.io.Serializable {
public Phone() {...}
public int getAreaCode() {...}
public void setAreaCode(int areaCode) {...}
public java.lang.String getExchange() {...}
public void setExchange(java.lang.String exchange) {...}
public java.lang.String getNumber() {...}
public void setNumber(java.lang.String number) {...}
public boolean equals(Object obj) {...}
public int hashCode() {...}
}
</pre>
<h4>Mapping XML to Java types : Metadata</h4>
<p>Notice in the mapping above, the XML type name is "phone" and the
generated Java class is "Phone" - the capitalization of the first
letter has changed to match the Java coding convention that classes begin with
an uppercase letter. This sort of thing happens a lot, because the rules for
expressing XML names/identifiers are much less restrictive than those for Java.
For example, if one of the sub-elements in the "phone" type above
was named "new", we couldn't just generate a Java field called "new",
since that is a reserved word and the resultant source code would fail to compile.</p>
<p>To support this kind of mapping, and also to enable the serialization/deserialization
of XML attributes, we have a <b>type metadata</b> system which allows us to
associate Java data classes with descriptors which control these things.</p>
<p>When the WSDL2Java tool creates a data bean like the Phone class above, it
notices if the schema contains any attributes, or any names which do not map
directly to Java field/property names. If it finds any of these things, it will
generate a static piece of code to supply a <b>type descriptor</b> for the class.
The type descriptor is essentially a collection of <b>field descriptors</b>,
each of which maps a Java field/property to an XML element or attribute.</p>
<p>To see an example of this kind of metadata, look at the "test.encoding.AttributeBean"
class in the Axis source, or generate your own bean from XML which uses attributes
or names which would be illegal in Java.</p>
<h4>Holders</h4>
<p>This type may be used as an inout or out parameter. Java does not
have the concept of inout/out parameters. In order to achieve this
behavior, JAX-RPC specifies the use of holder classes. A holder class
is simply a class that contains an instance of its type. For example,
the holder for the Phone class would be:</p>
<pre class="example">
package samples.addr.holders;
public final class PhoneHolder implements javax.xml.rpc.holders.Holder {
public samples.addr.Phone value;
public PhoneHolder()
{
}
public PhoneHolder(samples.addr.Phone value) {
this.value = value;
}
}
</pre>
<p>A holder class is <b>only</b> generated for a type if that type is used as
an inout or out parameter. Note that the holder class has the suffix "Holder"
appended to the class name, and it is generated in a sub-package with the "holders". </p>
<p>The holder classes for the primitive types can be found in javax.xml.rpc.holders.</p>
<h4>PortTypes</h4>
<p>The Service Definition Interface (SDI) is the interface that's derived
from a WSDL's portType. This is the interface you use to access the
operations on the service. For example, given the WSDL:</p>
<pre class="example">
<message name="empty">
<message name="AddEntryRequest">
<part name="name" type="xsd:string"/>
<part name="address" type="typens:address"/>
</message>
<portType name="AddressBook">
<operation name="addEntry">
<input message="tns:AddEntryRequest"/>
<output message="tns:empty"/>
</operation>
</portType>
</pre>
<p>WSDL2Java will generate:
<pre class="example">
public interface AddressBook extends java.rmi.Remote {
public void addEntry(String name, Address address) throws java.rmi.RemoteException;
}
</pre>
<p>A note about the name of the SDI. The name of the SDI is typically the
name of the portType. However, to construct the SDI, WSDL2Java needs
information from both the portType <b>and</b> the binding.
(This is unfortunate and is a topic of discussion for WSDL version 2.)
<p>JAX-RPC says (section 4.3.3): "The name of the Java interface is mapped
from the name attribute of the wsdl:portType element. ... If the mapping to
a service definition interface uses elements of the wsdl:binding ..., then
the name of the service definition interface is mapped from the name of the
wsdl:binding element."
<p>Note the name of the spec. It contains the string "RPC". So this spec,
and WSDL2Java, assumes that the interface generated from the portType is an
RPC interface. If information from the binding tells us otherwise (in
other words, we use elements of the wsdl:binding), then the name of the
interface is derived instead from the binding.
<p>Why? We could have one portType - pt - and two bindings - bRPC and
bDoc. Since document/literal changes what the interface looks like, we
cannot use a single interface for both of these bindings, so we end up with
two interfaces - one named pt and another named bDoc - and two stubs -
bRPCStub (which implements pt) and bDocStub (which implements bDoc).
<p>Ugly, isn't it? But you can see why it's necessary. Since
document/literal changes what the interface looks like, and we could
have more than one binding referring to a single portType, we have to
create more than one interface, and each interface must have a unique name.
<h4>
Bindings</h4>
A Stub class implements the SDI. Its name is the binding name with
the suffix "Stub". It contains the code which turns the method invocations
into SOAP calls using the Axis Service and Call objects. It stands
in as a <b>proxy</b> (another term for the same idea) for the remote service,
letting you call it exactly as if it were a local object. In other words,
you don't need to deal with the endpoint URL, namespace, or parameter arrays
which are involved in dynamic invocation via the Service and Call objects.
The stub hides all that work for you.
<p>Given the following WSDL snippet:
<pre class="example"><binding name="AddressBookSOAPBinding" type="tns:AddressBook">
...
</binding></pre>
<p>WSDL2Java will generate:
<pre class="example">public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub
implements AddressBook {
public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault
{...}
public AddressBookSOAPBindingStub(URL endpointURL,
javax.xml.rpc.Service service)
throws org.apache.axis.AxisFault
{...}
<br> public AddressBookSOAPBindingStub(javax.xml.rpc.Service service)
throws org.apache.axis.AxisFault
{...}
<br> public void addEntry(String name, Address address) throws RemoteException
{...}<br>}</pre>
<h4>
Services</h4>
Normally, a client program would not instantiate a stub directly.
It would instead instantiate a service locator and call a get method which
returns a stub. This locator is derived from the service clause in
the WSDL. WSDL2Java generates two objects from a service clause.
For example, given the WSDL:
<pre class="example"><service name="AddressBookService">
<port name="AddressBook" binding="tns:AddressBookSOAPBinding">
<soap:address location="http://localhost:8080/axis/services/AddressBook"/>
</port>
</service></pre>
<p>WSDL2Java will generate the service interface:
<pre class="example">public interface AddressBookService extends javax.xml.rpc.Service {
public String getAddressBookAddress();
<br> public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException;
<br> public AddressBook getAddressBook(URL portAddress) throws javax.xml.rpc.ServiceException;
}</pre>
<p>WSDL2Java will also generate the locator which implements this interface:
<pre class="example">public class AddressBookServiceLocator extends org.apache.axis.client.Service
implements AddressBookService {
...
}</pre>
<p>The service interface defines a get method for each port listed in the
service element of the WSDL. The locator is the implementation of this
service interface. It implements these get methods. It serves as
a locator for obtaining Stub instances. The Service class will by default
make a Stub which points to the endpoint URL described in the WSDL file,
but you may also specify a different URL when you ask for the PortType.
<p>A typical usage of the stub classes would be as follows:
<pre class="example">public class Tester
{
public static void main(String [] args) throws Exception {
// Make a service
AddressBookService service = new AddressBookServiceLocator();
// Now use the service to get a stub which implements the SDI.
AddressBook port = service.getAddressBook();
// Make the actual call
Address address = new Address(...);
port.addEntry("Russell Butek", address);
}<br>}</pre>
<h4>
Server-side bindings</h4>
Just as a stub is the client side of a Web Service represented in Java,
a <b>skeleton</b> is a Java framework for the server side. To make
skeleton classes, you just specify the "--server-side --skeletonDeploy true" options
to WSDL2Java.
For instance, using the AddressBook.wsdl as we had above:
<pre class="example">% java org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true AddressBook.wsdl</pre>
<p>You will see that WSDL2Java generates all the classes that were generated
before for the client, but it generates a few new files:
<br>
<br>
<table BORDER COLS=2 WIDTH="100%" >
<tr>
<td><b>WSDL clause</b></td>
<td><b>Java class(es) generated</b></td>
</tr>
<tr>
<td>For each binding</td>
<td>A skeleton class</td>
</tr>
<tr>
<td></td>
<td>An implementation template class</td>
</tr>
<tr>
<td>For all services</td>
<td>One deploy.wsdd file</td>
</tr>
<tr>
<td></td>
<td>One undeploy.wsdd file</td>
</tr>
</table>
<p>If you don't specify the "--skeletonDeploy true" option, a skeleton will not be
generated. Instead, the generated deploy.wsdd will indicate that the implementation
class is deployed directly. In such cases, the deploy.wsdd contains extra meta
data describing the operations and parameters of the implementation class.
Here is how you run WSDL2Java to deploy directly to the implementation:
<pre class="example">% java org.apache.axis.wsdl.WSDL2Java --server-side AddressBook.wsdl</pre>
<p>And here are the server side files that are generated:
<br>
<br>
<table BORDER COLS=2 WIDTH="100%" >
<tr>
<td><b>WSDL clause</b></td>
<td><b>Java class(es) generated</b></td>
</tr>
<tr>
<td>For each binding</td>
<td>An implementation template class</td>
</tr>
<tr>
<td>For all services</td>
<td>One deploy.wsdd file with operation meta data</td>
</tr>
<tr>
<td></td>
<td>One undeploy.wsdd file</td>
</tr>
</table>
<h4>
Bindings</h4>
<h5>
Skeleton Description (for Skeleton Deployment) </h5>
The skeleton class is the class that sits between the Axis engine and the
actual service implementation. Its name is the binding name with
suffix "Skeleton". For example, for the AddressBook binding, WSDL2Java
will generate:
<pre class="example">public class AddressBookSOAPBindingSkeleton implements AddressBook,
org.apache.axis.wsdl.Skeleton {
private AddressBook impl;
public AddressBookSOAPBindingSkeleton() {
this.impl = new AddressBookSOAPBindingImpl();
}
public AddressBookSOAPBindingSkeleton(AddressBook impl) {
this.impl = impl;
}
public void addEntry(java.lang.String name, Address address)
throws java.rmi.RemoteException
{
impl.addEntry(name, address);
}
}</pre>
<p>(The real skeleton is actually much richer. For brevity we just show
you the basic skeleton.)
<p>The skeleton contains an implementation of the AddressBook service.
This implementation is either passed into the skeleton on construction,
or an instance of the generated implementation is created. When the
Axis engine calls the skeleton's addEntry method, it simply delegates the
invocation to the real implementation's addEntry method.
<h5>
Implementation Template Description </h5>
<p>WSDL2Java also generates an implementation template
from the binding:
<pre class="example">public class AddressBookSOAPBindingImpl implements AddressBook {
<br> public void addEntry(String name, Address address)
throws java.rmi.RemoteException {
}
}</pre>
<p>This template could actually be used as a test implementation but, as
you can see, it doesn't do anything. It is intended that the service
writer fill out the implementation from this template.</p>
<p>When WSDL2Java is asked to generate the implementation template (via the --server-side
flag), it will ONLY generate it if it does not already exist. If this
implementation already exists, it will not be overwritten.</p>
<h4>Services</h4>
<p>The tool also builds you a "deploy.wsdd" and an "undeploy.wsdd" for each
service for use with the AdminClient. These files may be used to deploy
the service once you've filled in the methods of the Implementation class,
compiled the code, and made the classes available to your Axis engine.</p>
<h3><a NAME="Java2WSDL: Building WSDL from Java"></a>Java2WSDL: Building WSDL
from Java</h3>
The Java2WSDL and WSDL2Java emitters make it easy to develop a new web service.
The following sections describe the steps in building a web service from a Java interface.
<br>
<h4>
Step 1: Provide a Java interface or class</h4>
Write and compile a Java interface (or class) that describes the web service
interface. Here is an example interface that describes a web services
that can be used to set/query the price of widgets
(<a href="../samples/userguide/example6/WidgetPrice.java">samples/userguide/example6/WidgetPrice.java</a>):
<pre class="example">package samples.userguide.example6;
/**
* Interface describing a web service to set and get Widget prices.
**/
public interface WidgetPrice {
public void setWidgetPrice(String widgetName, String price);
public String getWidgetPrice(String widgetName);
}</pre>
<p><b>Note: </b>If you compile your class with debug information, Java2WSDL
will use the debug information to obtain the method parameter names.
<h4>
Step 2: Create WSDL using Java2WSDL</h4>
Use the Java2WSDL tool to create a WSDL file from the interface above.
<p>Here is an example invocation that produces the wsdl file (<tt>wp.wsdl</tt>)
from the interface described in the previous section (entered all on one line):
<pre class="example">% java org.apache.axis.wsdl.Java2WSDL -o wp.wsdl
-l"http://localhost:8080/axis/services/WidgetPrice" -n "urn:Example6"
-p"samples.userguide.example6" "urn:Example6" samples.userguide.example6.WidgetPrice</pre>
<p>Where:
<ul>
<li>
-o indicates the name of the <b><i>output WSDL</i></b> file</li>
<li>
-l indicates the<b><i> location of the service</i></b></li>
<li>
-n is the target <b><i>namespace</i></b> of the WSDL file</li>
<li>
-p indicates a mapping from the <b><i>package to a namespace</i></b>.
There may be multiple mappings.</li>
<li>
the class specified contains the interface of the webservice.</li>
</ul>
The output WSDL document will contain the appropriate WSDL types, messages,
portType, bindings and service descriptions to support a SOAP rpc, encoding
web service. If your specified interface methods reference other
classes, the Java2WSDL tool will generate the appropriate xml types to
represent the classes and any nested/inherited types. The tool supports
JAX-RPC complex types (bean classes), extension classes, enumeration classes,
arrays and Holder classes.
<p>The Java2WSDL tool has many additional options which are detailed in the <a href="reference.html#Java2WSDL">reference
guide</a>.
There is an <a href="ant/axis-java2wsdl.html">Ant Task</a> to integrate this
action with an Ant based build process.
<h4>
Step 3: Create Bindings using WSDL2Java</h4>
Use the generated WSDL file to build the appropriate client/server bindings
for the web service (see <a href="#WSDL2Java: Building stubs, skeletons, and data">WSDL2Java</a>):
<pre class="example">% java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true -Nurn:Example6 samples.userguide.example6 wp.wsdl</pre>
<p>This will generate the following files:
<ul>
<li> <b><tt>WidgetPriceSoapBindingImpl.java</tt></b> : Java file containing
the default server implementation of the WidgetPrice web service.</li>
<br>
You will need to modify the *SoapBindingImpl file to add your implementation
(see <a href="../samples/userguide/example6/WidgetPriceSoapBindingImpl.java">../samples/userguide/example6/WidgetPriceSoapBindingImpl.java</a>
).
<li> <b><tt>WidgetPrice.java</tt></b>: New interface file that contains
the appropriate <b><tt>java.rmi.Remote</tt></b> usages.</li>
<li> <b><tt>WidgetPriceService.java</tt></b>: Java file containing the client
side service interface.</li>
<li> <b><tt>WidgetPriceServiceLocator.java</tt></b>: Java file containing the
client side service implementation class.</li>
<li> <b><tt>WidgetPriceSoapBindingSkeleton.java</tt></b>: Server side skeleton.</li>
<li> <b><tt>WidgetPriceSoapBindingStub.java</tt></b>: Client side stub.</li>
<li> <b><tt>deploy.wsdd</tt></b>: Deployment descriptor</li>
<li> <b><tt>undeploy.wsdd</tt></b>: Undeployment descriptor</li>
<li> (data types): Java files will be produced for all of the other types
and holders necessary for the web service. There are no additional files
for the WidgetPrice web service.</li>
</ul>
<p>Now you have all of the necessary files to build your client/server side code
and deploy the web service!</p>
<h2>
<a NAME="published interfaces"></a>Published Axis Interfaces</h2>
Although you may use any of the interfaces and classes present in Axis, you need to
be aware that some are more stable than others since there is a continuing
need to refactor Axis to maintain and improve its modularity.
<p>Hence certain interfaces are designated as <i>published</i>, which means
that they are relatively stable. As Axis is refactored, the Axis developers
will try to avoid changing published interfaces unnecessarily and will
certainly consider the impact on users of any modifications.
<p>So if you stick to using only published interfaces, you'll minimise
the pain of migrating between releases of Axis. On the other hand, if you
decide to use unpublished interfaces, migrating between releases could
be an interesting exercise! If you would like an interface to be published,
you should make the case for this on the
<a href="mailto:axis-user@ws.apache.org">axis-user</a>
mailing list.
<p>The current list of published interfaces is as follows:
<ul>
<li>
JAX-RPC interfaces.
These interfaces are from JAX-RPC 1.0 specification, and will change only when
new versions of the specification are released.
<ul>
<li>javax.xml.messaging.Endpoint</li>
<li>javax.xml.messaging.URLEndpoint</li>
<li>javax.xml.rpc.Call</li>
<li>javax.xml.rpc.FaultException</li>
<li>javax.xml.rpc.JAXRPCException</li>
<li>javax.xml.rpc.ParameterMode</li>
<li>javax.xml.rpc.Service</li>
<li>javax.xml.rpc.ServiceException</li>
<li>javax.xml.rpc.ServiceFactory</li>
<li>javax.xml.rpc.Stub</li>
<li>javax.xml.rpc.encoding.DeserializationContext</li>
<li>javax.xml.rpc.encoding.Deserializer</li>
<li>javax.xml.rpc.encoding.DeserializerFactory</li>
<li>javax.xml.rpc.encoding.SerializationContext</li>
<li>javax.xml.rpc.encoding.Serializer</li>
<li>javax.xml.rpc.encoding.SerializerFactory</li>
<li>javax.xml.rpc.encoding.TypeMapping</li>
<li>javax.xml.rpc.encoding.TypeMappingRegistry</li>
<li>javax.xml.rpc.handler.Handler</li>
<li>javax.xml.rpc.handler.HandlerChain</li>
<li>javax.xml.rpc.handler.HandlerInfo</li>
<li>javax.xml.rpc.handler.HandlerRegistry</li>
<li>javax.xml.rpc.handler.MessageContext</li>
<li>javax.xml.rpc.handler.soap.SOAPMessageContext</li>
<li>javax.xml.rpc.holders.BigDecimalHolder</li>
<li>javax.xml.rpc.holders.BigIntegerHolder</li>
<li>javax.xml.rpc.holders.BooleanHolder</li>
<li>javax.xml.rpc.holders.BooleanWrapperHolder</li>
<li>javax.xml.rpc.holders.ByteArrayHolder</li>
<li>javax.xml.rpc.holders.ByteHolder</li>
<li>javax.xml.rpc.holders.ByteWrapperArrayHolder</li>
<li>javax.xml.rpc.holders.ByteWrapperHolder</li>
<li>javax.xml.rpc.holders.CalendarHolder</li>
<li>javax.xml.rpc.holders.DateHolder</li>
<li>javax.xml.rpc.holders.DoubleHolder</li>
<li>javax.xml.rpc.holders.DoubleWrapperHolder</li>
<li>javax.xml.rpc.holders.FloatHolder</li>
<li>javax.xml.rpc.holders.FloatWrapperHolder</li>
<li>javax.xml.rpc.holders.Holder</li>
<li>javax.xml.rpc.holders.IntHolder</li>
<li>javax.xml.rpc.holders.IntegerWrapperHolder</li>
<li>javax.xml.rpc.holders.LongHolder</li>
<li>javax.xml.rpc.holders.LongWrapperHolder</li>
<li>javax.xml.rpc.holders.ObjectHolder</li>
<li>javax.xml.rpc.holders.QNameHolder</li>
<li>javax.xml.rpc.holders.ShortHolder</li>
<li>javax.xml.rpc.holders.ShortWrapperHolder</li>
<li>javax.xml.rpc.holders.StringHolder</li>
<li>javax.xml.rpc.namespace.QName</li>
<li>javax.xml.rpc.server.ServiceLifecycle</li>
<li>javax.xml.rpc.soap.SOAPFault</li>
<li>javax.xml.rpc.soap.SOAPHeaderFault</li>
<li>javax.xml.transform.Source</li>
</ul>
</li>
<li>Axis interfaces. These have less guarantees of stability:
<ul>
<li>org.apache.axis.AxisFault</li>
<li>org.apache.axis.Handler</li>
<li>org.apache.axis.DefaultEngineConfigurationFactory</li>
<li>org.apache.axis.EngineConfiguration</li>
<li>org.apache.axis.EngineConfigurationFactory</li>
<li>org.apache.axis.Message</li>
<li>org.apache.axis.MessageContext</li>
<li>org.apache.axis.SOAPPart</li>
<li>org.apache.axis.client.Call</li>
<li>org.apache.axis.client.Service</li>
<li>org.apache.axis.client.ServiceFactory</li>
<li>org.apache.axis.client.Stub</li>
<li>org.apache.axis.client.Transport</li>
<li>org.apache.axis.description.TypeDesc</li>
<li>org.apache.axis.description.AttributeDesc</li>
<li>org.apache.aixs.description.ElementDesc</li>
<li>org.apache.axis.encoding.DeserializationContext</li>
<li>org.apache.axis.encoding.Deserializer</li>
<li>org.apache.axis.encoding.DeserializerFactory</li>
<li>org.apache.axis.encoding.DeserializerTarget</li>
<li>org.apache.axis.encoding.FieldTarget</li>
<li>org.apache.axis.encoding.MethodTarget</li>
<li>org.apache.axis.encoding.SerializationContext</li>
<li>org.apache.axis.encoding.Serializer</li>
<li>org.apache.axis.encoding.SerializerFactory</li>
<li>org.apache.axis.encoding.SimpleType</li>
<li>org.apache.axis.encoding.Target</li>
<li>org.apache.axis.encoding.TypeMapping</li>
<li>org.apache.axis.encoding.TypeMappingRegistry</li>
<li>org.apache.axis.encoding.ser.BaseDeserializerFactory</li>
<li>org.apache.axis.encoding.ser.BaseSerializerFactory</li>
<li>org.apache.axis.encoding.ser.BeanPropertyTarget</li>
<li>org.apache.axis.encoding.ser.SimpleSerializer</li>
<li>org.apache.axis.encoding.ser.SimpleDeserializer</li>
<li>org.apache.axis.session.Session</li>
<li>org.apache.axis.transport.http.SimpleAxisServer</li>
<li>org.apache.axis.transport.jms.SimpleJMSListener</li>
<li>org.apache.axis.utils.BeanProperty</li>
<li>org.apache.axis.wsdl.WSDL2Java</li>
<li>org.apache.axis.wsdl.Java2WSDL</li>
</ul>
</ul>
<h2><a name="newbie"></a>Newbie Tips: Finding Your Way Around</h2>
<p>So you've skimmed the User's Guide and written your first .jws service,
and everything went perfectly! Now it's time to get to work on a real project,
and you have something specific you need to do that the User's Guide didn't
cover.
It's a simple thing, and you know it must be in Axis <em>somewhere</em>, but
you don't know what it's called or how to get at it. This section is meant to
give you some starting points for your search.</p>
<h3>Places to Look for Clues</h3>
<p>Here are the big categories.</p>
<ul>
<li><a href="../samples/"><b>The samples.</b></a> These examples are
complete with deployment descriptors and often contain both client and
server code.
</li>
<li><b>The Javadocs.</b> Full Javadocs are included with the binary
distribution.
The Javadocs can be intimidating at first, but once you know the major user
classes, they are one of the fastest ways to an answer.</li>
<li><b><a href="http://ws.apache.org/axis/mail.html">The mailing list
archives.</a></b>
If you know what you want but don't know what it's called in Axis, this is
the best place to look. Chances are someone has wanted the same thing and
someone else has used (or developed) Axis long enough know the name.</li>
<li> Consult the <A HREF="http://ws.apache.org/axis">Axis web site</a> for updated documentation and the
<a href="http://nagoya.apache.org/wiki/apachewiki.cgi?AxisProjectPages">Axis Wiki</a>
for its Frequently Asked Questions (FAQ), installation notes,
interoperability issues lists, and other useful information.
</li>
<li> <b>WSDL2Java.</b> Point WSDL2Java at a known webservice that does some
of the things you want to do. See what comes out. This is useful even if
you
will be writing the actual service or client from scratch. If you want
nice,
human-readable descriptions of existing web services, try
<a href="http://www.xmethods.net">http://www.xmethods.net</a>.</li>
</ul>
<h3>Classes to Know</h3>
<h4>org.apache.axis.MessageContext</h4>
<p>The answer to most "where do I find..." questions for an Axis web
service is "in the MessageContext." Essentially everything Axis
knows
about a given request/response can be retrieved via the MessageContext. Here
Axis stores:</p>
<ul>
<li>A reference to the AxisEngine</li>
<li>The request and response messages (<code>org.apache.axis.Message</code>
objects available via getter and setter methods)</li>
<li>Information about statefulness and service scope (whether the service is
maintaining session information, etc.)</li>
<li>The current status of processing (whether or not the "pivot"
has
been passed, which determines whether the request or response is the
current
message)</li>
<li>Authentication information (username and password, which can be provided
by a servlet container or other means)</li>
<li>Properties galore. Almost anything you would want to know about the
message
can be retrieved via <code>MessageContext.getProperty()</code>.
You only need
to know the name of the property. This can be tricky, but it is usually a
constant, like those defined in
<code>org.apache.axis.transport.http.HTTPConstants</code>.
So, for example, to retrieve the ServletContext for the Axis Servlet, you
would want: <code>((HttpServlet)msgC.getProperty(HTTPConstants.MC_HTTP_SERVLET)).getServletContext();</code><br>
</li>
</ul>
<p>From within your service, the current MessageContext object is always
available
via the static method <code>MessageContext.getCurrentContext()</code>. This
allows you to do any needed customization of the request and response
methods,
even from within an RPC service that has no explicit reference to the
MessageContext.</p>
<h4>org.apache.axis.Message</h4>
<p>An <code>org.apache.axis.Message</code> object is Axis's representation of
a SOAP message. The request and response messages can be retrieved from the
MessageContext as described above. A Message has:</p>
<ul>
<li>MIME headers (if the message itself has MIME information)</li>
<li>Attachments (if the message itself has attachments)</li>
<li>A SOAPPart (and a convenience method for quick retrieval of the
SOAPPart's
SOAPEnvelope). The SOAPPart gives you access to the SOAP "guts"
of the message (everything inside the <soap:Envelope> tags)</li>
</ul>
<h4>org.apache.axis.SOAPEnvelope</h4>
<p>As you can see, starting with the MessageContext lets you work your way
down
through the API, discovering all the information available to you about a
single
request/response exchange. A MessageContext has two Messages, which each
have
a SOAPPart that contains a SOAPEnvelope. The SOAPEnvelope, in turn, holds
a full representation of the SOAP Envelope that is sent over the wire. From
here you can get and set the contents of the SOAP Header and the SOAP Body.
See the Javadocs for a full list of the properties available.</p>
<h2> <a NAME="tcpmon"></a>Appendix : Using the Axis TCP Monitor (tcpmon)</h2>
The included "tcpmon" utility can be found in the org.apache.axis.utils
package. To run it from the command line:
<pre>% java org.apache.axis.utils.tcpmon [listenPort targetHost targetPort]</pre>
Without any of the optional arguments, you will get a gui which looks like
this:
<center>
<p><img SRC="images/tcpmon1.jpg" height=599 width=599></center>
<p>To use the program, you should select a local port which tcpmon will
monitor for incoming connections, a target host where it will forward such
connections, and the port number on the target machine which should be
"tunneled" to. Then click "add". You should then notice another tab appearing
in the window for your new tunneled connection. Looking at that panel,
you'll see something like this:
<center>
<p><img SRC="images/tcpmon2.jpg" height=600 width=599></center>
<p>Now each time a SOAP connection is made to the local port, you will
see the request appear in the "Request" panel, and the response from the
server in the "Response" panel. Tcpmon keeps a log of all request/response
pairs, and allows you to view any particular pair by selecting an entry
in the top panel. You may also remove selected entries, or all of them,
or choose to save to a file for later viewing.
<p>The "resend" button will resend the request you are currently viewing, and
record a new response. This is particularly handy in that you can edit the XML
in the request window before resending - so you can use this as a great tool
for testing the effects of different XML on SOAP servers. Note that you may
need to change the content-length HTTP header value before resending an edited
request.
<h2> <a NAME="soapmon"></a>Appendix: Using the SOAP Monitor </h2>
Web service developers often have the need to see the SOAP messages
being used to invoke web services along with the results of those
messages. The goal of the SOAP Monitor utility is to provide
a way for these developers to monitor the SOAP messages being used
without requiring any special configuration or restarting of the
server.
<p>
In this utility, a handler has been written and added to the global
handler chain. As SOAP requests and responses are received, the SOAP
message information is forwarded to a SOAP monitor service where it
can be displayed using a web browser interface.
<p>
The SOAP message information is accessed with a web browser by going
to http://localhost:<port>/axis/SOAPMonitor (where
<port> is the port number where the application server is
running).
<p>
The SOAP message information is displayed through a web browser
by using an applet that opens a socket connection to the SOAP
monitor service. This applet requires a Java plug-in 1.3 or
higher to be installed in your browser. If you do not have a
correct plug-in, the browser should prompt you to install one.
<p>
The port used by the SOAP monitor service to comminicate with
applets is configurable. Edit the web.xml file for the Axis
web application to change the port to be used.
<b>Note: The SOAP Monitor is NOT enabled by default for security reasons.</b>
To enable it, read <a href="install.html#soapmon">Enabling the
SOAP Monitor</a> in the Installation instructions.
<a NAME="Glossary">
<h2>Glossary</h2></a>
<dl>
<dt> <i>Handler</i></dt>
<dd> A reusable class which is responsible for processing a MessageContext in
some custom way. The Axis engine invokes a series of Handlers whenever a request
comes in from a client or a transport listener.</dd>
<dt> <i>SOAP</i></dt>
<dd> The Simple Object Access Protocol (yes, despite the fact that it sometimes
doesn't seem so simple, and doesn't have anything to do with objects... :)).
You can read the SOAP 1.1 specification at <a href="http://www.w3.org/TR/SOAP">http://www.w3.org/TR/SOAP</a>.
The W3C is currently in the midst of work on SOAP 1.2, under the auspices
of the <a href="http://www.w3.org/2000/xp/Group/">XML Protocol Group</a>.</dd>
<dt> <i>Provider</i></dt>
<dd> A provider is the "back-end" Handler which is responsible for
actually performing the "meat" of the desired SOAP operation. Typically
this means calling a method on some back-end service object. The two commonly
used providers are RPCProvider and MsgProvider, both in the org.apache.axis.providers.java
package.</dd>
</dl>
</body>
</html>
|