Advanced Java Networking

Advanced Java Networking

ID:40878226

大小:1.89 MB

页数:363页

时间:2019-08-09

上传者:新起点
Advanced Java Networking_第页
预览图正在加载中,预计需要20秒,请耐心等待
资源描述:

《Advanced Java Networking》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库

IntroductionBynowyou'veseenallthehype,readallthebooks,anddiscoveredallthewondersofJava.ButmostofusstilluseC++orCtocreateourhard-coreapplications,savingJavaforourWebpagesorleavingittoHTMLjockstofiddlewith.Doingsodeniesustheopportunitytouseaprogramminglanguagethatmakesinterfacingwithacomputerinfinitelyeasier,withlessfrustrationandfasterresults.Javaismuchmorethan"DancingDukes"oraprogramminglanguageforWebpages.Itisastrongalternativetothemasochisticprogrammingofthepast,inwhichcountlessmonthswerespentdebuggingcomparedtothemeredaysittooktocodetheinitialconcept.Javaallowsustospendmoretimeintheconceptualphaseofsoftwaredesign,thinkingupnewandcreativewaystobringthevastknowledgeoftheInternetanditsmanyuserstoourdesktop.Today,ourinformation,anditssteadyflow,isgarneredfromtheInternetandthemillionsoffellowcomputerusersaroundtheworld.Upuntilnow,you'venodoubtdesignedprogramstointerfacewiththatknowledgeusingCorC++.Javawillchangeallofthat.InadditiontoitsabilitytocreateadorableandfunctionaluserinterfacesquicklyandeasilyisJava'sabilitytoeasilyconnecttotheInternet.Javais,afterall,theInternetLanguage.WhatThisBookIsAllAboutAdvancedJavaNetworkingisdesignedtopresentyouwithamyriadofalternativestoconnectyourapplicationstotheInternet.Itisneitheraprogrammingreferencenoramarketingbrochure.We'llleavethattothegeeksandmarketeerstobattleout.Instead,wewantedtoexploreeachalternativewithoutmarketingbiasorengineeringsnobbery.Onepartoftheengineeringcommunitywilltellyouthatsocketsaretheonlytruewaytocommunicateinformationoveranetwork.AnothersegmentwillsaythatJava-onlyapplicationsrelyingonRemoteMethodInvocation(RMI)willsolveallyour communicationproblems.Then,ofcourse,thereistheCommonObjectRequestBrokerArchitecture(CORBA)camp.We'lldiscussthesealternatives,andwewillalsoexploreaspectsofserver-sideprogramminginwhichweuseaWebserverasamechanismtogeneratedynamicWebpagesthatcanbeconnectedtodatabases(andjustaboutanythingelse).Wepresentanhonestaccountofeachalternativeandguidelinesforchoosingwhat'sbestforyourbusinessorprogrammingneeds.InadditiontothehundredsoflinesofsamplecodewesupplytohelpyoustartfromscratchwithJavacommunication,weplaceanadditionalemphasisonmigrationofyourexistingdesktop-centricapplicationstoanInternet-readyworld.WhoShouldReadThisBookThisbookisnotforbeginningprogrammersnorisitanintroductoryJavatext.Weassumethatyouhaveastrongobject-orientedprogrammingbackground,preferablyinJava.YoushouldhaveastronggraspofsuchJavafundamentalsashowtocreateaclass,howtocompileandexecuteprogramsonyournativesystem,andhowtodeployJavaapplications.Furthermore,youshouldunderstandagooddealoftheterminologyoftheobject-orientedworld.HowtoReadThisBookWe'veconceivedthisbookinparts,witheachpartfurtherdividedinchapters.EachpartaddressesoneaspectofInternetprogramming,beitJavaFundamentals;CoreNetworkingsuchasRMI,CORBA,orJavaDatabaseConnectivity(JDBC);AdvancedNetworkinglikeBeansandWebServers;generalJavaNetworkinginformation,includingaspecialchapteronInternetsecuritythataddressessimpleAppletSecurityrestrictions;ormorecomplexsubjectssuchasDirectoryServicesandJNDI.WehavealsoincludedashortchapterthatisanintroductiontoTCP/IPandhowtheInternetworks.IhavefoundthisinvaluableastheveryfirstthingthatwecoverintheInternetProgrammingcourseIteach.Finally,wewanttoshowyouthatJavaprogrammingismuchmorethanananimationfloatingbyaWebpageorinteractiveInternetcontent.Javaisalanguagethatcanholditsownintheworldofdesktopapplicationsandtheexamplesinthebooktypicallyarewrittenasapplicationsratherthanasapplets.WemakenoefforttocontainourenthusiasmforJavaandcertainlydon'tapologizeforourdelightinworkingwithit.Wehopethatyouwillcometolovethislanguageasmuchaswehave.ConventionsWeusethemonospacedCourierfonttodenotesourcecodeandtypeoutourcodelistings.IfyouseeaCourierwordwithinasentence(forexample"JavaVectorsarecool"),itisthenameofaclassorobject.Wearealsofirmbelieversinthestep-by-stepapproachtocodesamples.Therefore,wehavegenerallyshowntheentirecodelistingandtheadditionsfromthepreviousinstanceofit.ThechangesareinCourierBold.Forexample,thefirsttimeweshowacodesnippet,itlookslikethis:publicclassDick{ }Andwhenwemakeanadditionitisbolded:publicclassDick{Stringloves="Bobbie";}Also,whenweshowacommandprompt,thepartyoutypeisalsobolded:%prompt%dirc:gamesTherearesidebarsthroughoutthisbookthathighlightcertainpartsofthetext,asfollows.•TipsinformyouofaspecialoruniquewaytoaccomplishsomethinginJavanetworking.•Alertstellyouofanybugsor"gotchas"thatyoushouldbeawareofwhileprogrammingyourapplications.•Notessimplypointoutanyinformationthatmightbeusefultoyouinyournetworkprogrammingendeavors.FixesandUpdatesWewouldalsoliketotakeamomenttoapologizeinadvanceforanyerrors.Thisbookhasbeenatotalblasttowrite,andwemighthavegottencaughtupinourownexcitementhereandthere.Inanyevent,wehopeyouhavefunreadingaboutandexploringtheJavanetworkedworld!TheCD-ROMthataccompaniesthisbook(see"AbouttheCD-ROM,"atthebackofthebookfordetailsregardingtheCD-ROM)containsseveraloftheapplicationsthatwehavedevelopedinthisbook.Additionally,aspecialWebpagehasbeencreatedasafront-endtonavigatingtheCD-ROMandforlinkingtorelatedWebsites.ToaccessthatWebpage,pleaseloadthefilenamedindex.html,foundintherootdirectoryoftheCD-ROM,intoyourbrowser.Toerrishuman,andtheauthorsofthisbookareashumanascanbe.Despitetestingeveryexamplethoroughly,bothfromaninstallationandcompilationperspective,problemscanoccur.Ifwefindaproblemwithanyoftheprogrammingexamplesinthisbook,wewillpostafixassoonaspossibleonourWebsite:http://www.prenhall.com/~java_sun ThisonlineWebsupplementcanalsobelinkedtofromtheWebpageincludedontheCD-ROMincludedwiththisbook.ThanksaMillion!AboutthetimethatPrashantSridharanwrotethefirsteditionofthisbook,Istartedteachinganundergraduatecoursetitled(innocentlyenough)InternetProgramming(CS-328).MypersonalgoalsforthecoursewerethatitwouldbeJavabasedandthatitwouldcoverTCP/IP,socketsprogramming,theuseofdatabases,anddistributedobjectprogramming.In1997,thereweretextbooksonnetworkingandtextbooksonJava,buttherewerenotextbooksonnetworkingusingJava.IfoundPrashant'sbookinthetradebooksectionofourlocalbookstore.Topically,itwasalmostaperfectfitforthecourseoutlinethatIhaddeveloped.CS-328beganinthefallof1997,withPrashant'sbookasitstext.Thecoursehasbeenimmenselypopularandhasbeenofferedtoafullhouseofjuniorsandseniorseverysemestersince.Writingthesecondeditionofthisbookhasbeenabalancingactthathasbeenfrustratingattimes;rewardinginthesupportofcolleagues,friends,andfamily;and—toseeone'seffortsinprint—quitesatisfying.Ihadneverhadtheslightestdesiretotacklethetaskofauthoringabook,especiallyatechnology-basedbook.AsanadjunctfacultymemberintheComputerScienceDepartmentintheT.J.WatsonSchoolofEngineeringandAppliedScienceatBinghamtonUniversity(StateUniversityofNewYork)forthelast25years,Ihavetaughtmanydifferentprogrammingcoursesandusedtextsbymanyauthors,frommanysources.Ifoundthat,afterusingthesametextbookforseveralsemesters,Iwouldhavecollectedalistofcorrectionsandsuggestionsforimprovementsandupdatesinordertokeepthecoursematerialcurrent.Afterfoursemesters(twoyears—alongtimeinthelifeofJava)withthefirstedition,Idecidedthatthematerialinthebookwasgettingalittlestale.Afterall,JavahadprogressedtoJDK1.1.7andtheexamplesinthebookwerestillJDK1.0.ManyofthepredictionsmadeaboutthecoursethatJavawouldtakehadnotmaterialized.Thebookcriedoutforasecondedition.Likeanygoodinstructor,IphonedthepublisherandeventuallywasputintouchwithMarkTaub.IaskedMarkwhenthesecondeditionwouldbeoutandwastoldthathewishedthathecouldtellme:PrashantnolongerworkedforSunandhadtakenanewjobatMicrosoft(nowthere'sadefectionforyou)anddidn'thavethetimerequiredforasecondedition.MarkthendidsomethingIneverexpectedandaskedinnocently,"Youseemtoknowwhatthebookneedsandyou'vebeenusingitforquiteawhile,wouldyoubeinterestedintacklingthesecondedition?"Aftermuchsoulsearchinganddiscussionwithmywifeandmyassociatesinacademia,LesLander,MargaretIwobi,andEileeneHead,IcalledMarkback.ItoldMarkthatdespitemydoubts,myassociatesthoughtthatitwouldbeagoodopportunityforgrowth(andwhatelsedidIhavetodowithmytime?).Conveniently,theyseemedtoforgetthatIworkfulltimeasanAdvisoryProgrammeratLockheedMartinFederalSystems,Owego,NewYork,whereIamalsothesiteWebmaster.Ithasbeenabusy10monthssincemyfirstcontactwithMark.I'vereallyhadfundoingthisandamreallygratefultoMarkandPrenticeHallforgivingmetheopportunitytoinvestigateandwriteaboutJavaNetworking(oneofmyfavorite topics).I'mgrateful,too,forthehelpAnneTrowbridgeofPrenticeHallgavemewiththeCD-ROMthataccompaniesthebook.ThereareanumberofpeoplethatImustcreditfortheirhelpwithgettingthisbooktomarket.Firstandforemostismywife,Bobbie,towhomIhavebeenmarriedfor32years.ShehaspatientlysupportedmethroughmoreprojectsthanIcaretocount.IowespecialthankstoassociatesatLockheedMartin:firsttomymanagerMaryLouMarcotteforlettingmedivvyuplastyear'svacationinthestrangewaythatIdidtocompletethewriting.MaryLou,It'shardadjustingtoanormalscheduleagain.ScottRush,oursiteelectronicsecurityguruhelpedmewiththechapteronJavasecurity.MyveryspecialthanksgotoNoahTernullo.Noahisbothaworkassociateandoneourgraduatestudentsattheuniversity.CS-328isanundergraduatecourse;however,becauseitisanInternet-basedcourse,itattractsalotofgraduatestudents.GraduatestudentswantingtotakeCS-328mustregisterforIndependentStudy,successfullycompletethecourse,anddoanadditionalresearchprojectinamutuallyagreedupontopicinJavanetworking.Theypresenttheirproject(alongwithapaper)totheclassattheendofthesemester.AtthetimeNoahwasagraduatestudentinmyclass,SunhadjustannouncedJINI,andhedecidedthatthatwaswhathewantedtoresearch.ThenightthatNoahdidtheclasspresentation,heandafrienddraggedthreePCsintotheclassroomfromtheircarsandseteverythingup.OnemachinewasrunningLinux;another,NT;andthethird,W95.ThepresentationwasnotonlyagreatdemonstrationofJavaportability,butareallygooddemonstrationofJINI.IwassoimpressedthatIinvitedNoahtowritethechapteronJINI.Ihopethathiscontributiontothistextwillhelphimfulfillhisdreamsforenteringadoctoralprogram.SpecialthanksalsogotomycourseassistantforCS-328,EdwinChiu.Edwinhasbeenwithmethroughfivesemestersandhasnowearnedhisbachelor'sdegreeandiscurrentlyapplyingtograduateschools.EdwintackledtheconversionoftheInternetAppointmentCalendarfromJoetotheVisibrokerOrb.AdditionalthanksgotoPeterDeAngelisofLockheedMartinforcomingtoouraidwhenitlookedlikeVisibrokerhadgottenthebestofusandtoElaineMurrayforherreviewofthegeneralinformationpartoftheCORBAchapter.Last,butnotleastIowearealdebttotheproductionteamfromBooksCraft:DonMacLaren,BillHartman,andSaraBlack.WithoutDongentlyremindingmeofproductionscheduleswewouldn'tbeatthispoint.Finally,letusnotforgetPrashantSridharan.IowePrashantthegreatestthanksbothforwritinganexcellentfirsteditionandthenforchangingjobssothatIcouldwritethesecondedition.MuchofwhatPrashantwroteinthefirsteditionisstillincluded,stillapplicable.We,PrashantandI,bothhadalotoffunbringingthisbooktoyou.Wehopethatyou'llfinditasusefulaswefounditfun. Chapter1.AdvancedJava•BasicJava•JavaI/ORoutines•IntroductiontoThreadinginJava•ObjectSerialization•Performance•AFirstLookatJavaNetworkinginActionOurtourofJavanetworkingbeginswithasimpleandquicktutorialonseveraloftheadvancedfeaturesoftheJavaprogramminglanguage.Fromthere,wedivestraightintotheapplicationprogramminginterfaces(APIs)associatedwithconnectingJavaobjectsacrossdisparatemachinesandnetworks.EachoftheseAPIshasbothstrengthsandweaknesses,andwecertainlyhighlightthestrengthswhileexposingtheweaknesses.Finally,wedescribethetoolsnecessarytoprovideasafeenvironmentforyourJavaapplications,withoutsacrificingthepowerofthelanguageitself.Ourdiscussionbeginshere,withthefastestobject-orientedtutorialthissideoftheMississippi.BasicJavaWhenbeginnersfirsttaketoC++,theirprimalscreamscanbeheardformiles.Often,emergencycrewsaredispatchedimmediatelytopreventtheseriousinjuriesthataretypicallyenduredwhenbeginnersarefirstconfrontedwiththedreaded*pointer->.Enoughtomakeagrownmancry,C++isapowerfulyetincrediblydifficultlanguage.EnterJava.Javaisobject-oriented,modular,elegant,and—inthehandsofamaster—quitepoetic!Javacodecanbebeautifulandpowerful,funandexciting,and,mostimportantly,incrediblyuseful!ThischapterfocusesonsomeoftheadvancedconceptsyouneedtograspinordertosupportyourfurtherendeavorsusingJava.Throughoutthediscussion,youwillseesamplecodethathighlightssomeofJava'sinherentlyobject-orientedfeatures:encapsulationandinformationhiding,modularity,inheritance,andelegance.Weintendthischaptertoprovideyouwithabaseofterminology,notacomprehensiveJavalanguagetutorial.Beginnersshouldbeforewarned:Thisbookassumesyouknowthelanguage.Muchofwhatisdiscussedinthischapteristhefundamentaldesignaspectsofanobject-orientedlanguage.Forseasonedprogrammers,theurgetoskipthischapterwillbestrong.However,manyoftheadvancedfeaturesofJava,aswellasthearchitecturaldecisionsthatmustbemadeforaJavanetworkedapplication,arebasedonthefundamentalconceptswedescribeinthischapterandareofgreatimportancetobothveteranandrookienetworkingprogrammersalike.Object-OrientedDesignUsingJavaInJava,youdeclareclassesasacollectionofoperationsperformedonasetofdata.Becausedatacannotbepassedbyreference(Javaisapointer-freelanguage—letthe cheeringbegin!),Javaclassesareneededtocontaindatasothatitcanbemodifiedwithinotherclasses.Classesvs.InterfacesTheprevailingassumptionaboutJavaisthatyouareunabletoseparateimplementationsfrominterfaces.However,thisassumptionisfalse.Javaprovidesaninterfacecomponentthatissimilartoitsclasscounterpartexceptthatitisnotpermittedtohavememberfunctions.Indeed,otherobjectsthatwillimplementitsmethodandvariabledefinitions,asillustratedinthefollowingsnippet,mustreusethisinterface.publicinterfaceMyAdvancedJavaInterface{publicabstractvoidmethodOne();void.methodTwo();}publicclassMyAdvancedJavaClassimplementsMyAdvancedJavaInterface{MyAdvancedJavaClass(){}publicvoidmethodOne(){...}publicvoidmethodTwo(){...}}Allmemberfunctionsdeclaredwithininterfacesare,bydefault,publicandabstract.Thismeansthattheyareavailableforpublicconsumptionandmustbeimplementedinaclassbeforetheycanbeused.Furthermore,interfacesdonothaveconstructorsandmustbeextendedbeforetheycanbeused.DataMembersGoodobject-orientedstyledictatesthatalldatamembersofaclassshouldbedeclaredprivate,hiddenfromanyoperationsotherthanthoseincludedintheclassitself.But,anyexperiencedobject-oriented(OO)programmerwilltellyouinnouncertaintermsthatthisisoftenstupidandinaneforsmallclasses.BecausestructsarenotavailableinJava,youcangroupdataintoonecontainerbyusingaclass.Whetheryousubscribetotheartificiallyenforcedprivate-data-memberschemeofC++orthelanguage-enforcedschemeofSmalltalkisentirelyuptoyou.Java,however,assumesthatdatamembersarepublicunlessotherwiseinstructed,asthefollowingsnippetsuggests. publicclassMyAdvancedJavaClass{publicintnumItems;privateintitemArray[];};MethodsAnotherimportantcomponentoftheJavaclassistheoperation,ormethod.Methodsallowoutsideclassestoperformoperationsonthedatacontainedinyourclass.Byforcingotherclassestoutilizeyourdatathroughtheclasses,youenforceimplementationhiding.Itdoesn'tmattertootherclassesthatyourcollectionofdataisanarray,forasfarasthoseclassesareconcerned,itcouldbeaVector.Somewheredowntheline,youcouldchangetheimplementationtoaHashTableifefficiencybecomesaconcern.Thebottomlineisthattheclassesthatuseyourmethodsdon'tcare,anddon'tneedtoknow,solongasthemethodsignature(themethodnameanditsaccompanyingparameters)remainsthesame.Thefollowingcodeshowshowamethodcanbeintroducedwithinaclass.publicclassMyAdvancedJavaClass{publicintnumItems;privateintitemArray[];publicvoidaddItem(intitem){itemArray[numItems]=item;numItems++;};};ConstructorsBut,thereisonesmallproblemwiththisexample.Thedataisneverinitialized!Thisiswherethenotionofconstructorscomesin.Constructorssetupaclassforuse.Classesdon'tneedtospecifyaconstructor;indeedaconstructoris,bydefault,simplyafunctioncalltonothing.Inthiscase,however,ourclassmustcallaconstructorbecauseourdataneedstobeinitializedbeforeitcanbeused.InJava,everythingisinheritedfromthesuperclassObject.AllObjectsmustbeinitialized,orallocated,beforetheyareused.Forexample,thedeclarationpublicintnumItems; specifiesanintegervalue.Theintisaprimitivetype,butjustlikeanObject,andthereforeintneedstobeinitialized.WecandosointhedeclarationitselfpublicintnumItems=0;orwecanusetheconstructorandinitializethearrayaswellpublicclassMyAdvancedJavaClass{publicintnumItems;privateintitemArray[];MyAdvancedJavaClass(){numItems=0;itemArray=newint[10];}publicvoidaddItem(intitem){itemArray[numItems]=item;numItems++;};};Keepinmindthatinitializingavariableatitsdeclarationaffordslittleflexibilityforanyclassesormethodsthatsubsequentlywilluseyourobject.Aconstructorcanbemodifiedeasilytoacceptincomingdataaswell,enablingyoutomodifyyourobjectdependingonthecontextofitsuse:publicclassMyAdvancedJavaClass{publicintnumItems;privateintitemArray[];MyAdvancedJavaClass(intinitialValue,intarrayLength){numItems=initialValue;itemArray=newint[arrayLength];}publicvoidaddItem(intitem){itemArray[numItems]=item;numItems++;};}; Anobjectisallowedtohaveseveralconstructors,solongasnotwoconstructorshavethesamemethodsignature(parameterlist):publicclassMyAdvancedJavaClass{publicintnumItems;privateintitemArray[];MyAdvancedJavaClass(){numItems=0;itemArray=newint[10];}MyAdvancedJavaClass(intinitialValue,intarrayLength){numItems=initialValue;itemArray=newint[arrayLength];}publicvoidaddItem(intitem){itemArray[numItems]=item;numItems++;};};Sometimes,confusionmayarisewhenthereareseveralconstructorsthatalldothesamething,butwithdifferentsetsofdata.InJava,constructorsareallowedtocallthemselves,eliminateduplicatecode,andenableyoutoconsolidateallyourconstructorcodeinoneplace:MyAdvancedJavaClass(){/*Insteadof…numItems=0;itemArray=newint[10];*///callthemorespecificconstructorthis(0,10);}MyAdvancedJavaClass(intinitialValue,intarrayLength){numItems=initialValue;itemArray=newint[arrayLength];}Constructorsarepowerfultools.Theyenableyoutocreateclassesandusethemdynamicallywithoutanysignificanthard-coding.Aswewillsee,goodconstructordesignisessentialtoanobject-orientedarchitecturethatworks. CreatingandInitializinganObjectWementionedearlierthatallJavaclassesinheritfromtheObjectsuperclass.TheconstructorforanObjectisinvokedusingthenewoperation.Thisinitializationoperationisusedatobjectcreationandisnotusedagainduringtheobject'slifecycle.Oneexampleofanobjectbeinginitializedisthearrayinitializationinoursampleclass.Thenewoperationfirstallocatesmemoryfortheobjectandtheninvokestheobject'sconstructor.Becausewecreatedtwokindsofconstructors,oursampleclasscanbeinvokedinoneoftwoways:myAdvancedJavaInstance1=newMyAdvancedJavaClass();myAdvancedJavaInstance2=newMyAdvancedJavaClass(10,100);Thefirstinstanceofourclassisinitializedtothedefaultvalues0and10.Whenweinvokedthenewoperationonthisinstance,thenewoperationsetthevaluesappropriately,andcreatedanewinstanceofArraywithintheclassinstance.ThesecondinstanceofourclasssetnumItemsto10andcreateda100-itemArray.Asyoucansee,thiskindofdynamicclasscreationisveryflexible.Wecouldjustaseasilycreateanotherinstanceofourclasswithentirelydifferent(orthesame)initialvalues.Thisisoneofthebasicprinciplesofobject-orienteddesignespousedbylanguagessuchasJava.Eachinstanceoftheobjectmaintainsasimilar-lookingbutentirelydifferentsetofvariables.Changingthevaluesinoneinstancedoesnotresultinachangeinthevaluesofthevariablesoftheotherinstances.Remember,aninstanceofaclassislikeyourBMW328iconvertible.AstheanalogyinFigure1-1illustrates,itlooksascoolaseveryotherBMW328i,butjustbecauseyoumodifyyourstoremovetheannoyingelectronicinhibitionofspeed,thatdoesn'tmeaneveryotherBeemeralsowillbechanged!Figure1-1.JustascustomizingyourBMWmakesitdifferentfromotherBMWs,modifyingvariablesinoneinstancedoesn'tchangetheminallinstances. ApplyingGoodObject-OrientedDesignSkillsMaybeyou'retiredofdrivingyourminivanbecauseyourhusband(orwife)makesyou!WhatyoureallywantisaBMWZ3roadster.So,youdriveyourbehemothToyotavandowntothenearestBMWdealerandtradeitinfortheZ3.Now,becauseyouhaveadifferentcar,doesthatmeanyouhavetolearnhowtodrivealloveragain?Thisisobviouslynotthecase(unlessyoujusttradedinaVolvo,inwhichcaseyouhavetolearntodrivetobeginwith).That'sbecausetheworld,yesthesameworldthatbroughtyouElvisandHillaryClinton,isinherentlyobject-oriented.InheritanceYourZ3,andeveryothercarontheroad,isacar,pureandsimple.Allcarshaveaccelerators,brakes,steeringwheels,and,eventhoughyoudon'tusetheminaBeemer,turnsignals.Ifwetakethisanalogyfurther,wecansaythateverycarinheritsfromthesame"baseclass,"asillustratedinFigure1-2Figure1-2.Inanyobject-orientedenvironment,classesinheritthecharacteristicsoftheirbaseclasses.Abaseclassisaspecialkindofobjectthatformsthefoundationforotherclasses.InJava,abaseclassisusuallyinheritedlateron.Thinkofderivedclassesas"kindsof"baseclasses.Inotherwords,"aBMWZ3isakindofcar."Withthatinmind,wecreatethefollowingclassstructure: publicclassCar{}publicclassBMWZ3extendsCar{}TheextendskeywordtellstheBMWZ3classtoutilizetheproperties,values,andbehavioroftheCarbaseclass.Butthereisonesmallproblem.Canyoueverdriveageneric"car"?No,becausethereisnosuchthing.Therearealwayskindsofcars,butneveraspecificthingthatisknownsimplyasacar.Javagivesusthenotionofan"abstractbaseclass."Anabstractbaseclassis,quitesimply,aclassthatmustbeinheritedfrom.Itcanneverbeusedasastand-aloneclass.InJava,theabstractkeywordgivesaclassthisuniqueproperty.publicabstractclassCar{inttopSpeed;}publicclassBMWZ3extendsCar{}Inthissituation,theCarclasscanneverbeinstantiatedorusedasis.Itmustbeinherited.WhentheBMWZ3classinheritsfromCar,italsoobtainsallthevariablesandmethodswithintheCarclass.So,ourBMWZ3classgetstousetopSpeedasifitwereitsownmembervariable.Somewhereinyourcodeyoumightwanttocheckwhattypeofvariableyouareusing.Javaprovidestheinstanceofkeywordtoenableyoutoinquireastowhattheabstractbaseclassofanobjectis.Forexample,thefollowingtwocodesnippetswouldreturnthevaluetrue:BMWZ3bmwVariable;FordTaurusfordVariable;if(bmwVariableinstanceofCar)...if(fordVariableinstanceofObject)...whereasthefollowingcodesnippetwouldreturnthevaluefalse. if(bmwVariableinstanceofPandaBear)NoticethatJava'sinheritancemodelisquitesimple.InC++,objectsareallowedtoinheritfromoneormoreabstractbaseclassesandcanbemadetoinherittheimplementationofthoseinterfacesaswell.Java,asamatterofsimplicity,doesnotallowthis,nordoesitplantoatanytimeinthefuture.Therearewaystogetaroundmultipleimplementationinheritance,buttheydonotreallyinvolveinheritanceatall.Thebottomlineisthatifyouneedtousemultipleimplementationinheritance,youprobablywon'twanttouseJava.CodeReuseLet'ssaythatyouareputtingtogetheryourson'sbicycleonChristmasmorning.TheinstructionscallforyoutouseaPhillips-headscrewdriver.Youtakethescrewdriveroutofthetoolbox,useit,andputitback.Afewminuteslater,youneedthescrewdriveragain.Surelyyouwouldusethesamescrewdriver,notgotothehardwarestoreandbuyanewone!Likewise,codereuseisofvitalimportancetotheprogrammeronatightschedule.Youwillneedtostreamlineyourcodesothatyoucandistributecommonlyusedtaskstospecificmodules.Forexample,manyoftheonlinedemonstrationsweprovidewiththisbookincludeanimationexamples.Ratherthanrecreatetheanimationroutines,wereusedthesamesetofanimationtoolswedevelopedbeforehand.Becausewecodedtheanimatorswithreuseinmind,wewereabletotakeadvantageofastronginterfacedesignandaneffectiveinheritancescheme.OOP—Strong,Efficient,andEffectiveWhew!WhetherthisisyourfirstforayusingtheJavalanguageoryour101st,allofyourdesignbeginsinthisoneplace.Therearethreestepstocreatinganobjectthatyoucanusetimeandagain:1.Stronginterfacedesign2.Efficientclassimplementation3.EffectiveinheritanceWiththefundamentalsofobject-orientedprogrammingunderyourbelt,youarereadytoexplorethesimplicitywithwhichyoucancreateprogramsinJavathathandleinputandoutput.TheJavaI/Oroutinesarenotonlyeasy,butextremelypowerful.BringingyourC++I/OtoJavawillresultinaslittlefunctionallossasmigratingobject-orienteddesigntechniquestoJavafromC++.JavaI/ORoutinesJavaprovidesseveraltoolsfortheinputandoutputofdata,rangingfromtheAbstractWindowToolkit(AWT)ortheSwingComponentstothecoreSystemfunctionsofJavaclasses.TheAWTisexactlywhatitsaysitis:asetofcomponentsfordesigningwindowsandgraphicaluserinterfacesthatusesthepeercomponentsofthe underlyingoperatingsystemfortheirimplementation.TheSwingComponentsdothesamething,butratherthanusingthepeercomponentsofthehostoperationsystem,allthecomponentsare100%pureJavacomponentsandcantakeonthelookandfeelofthecomponentsofthehostoperatingsystemorhavetheirown"custom"lookandfeel.ThecoreSystemclassesarebuilt-inroutinesforgatheringanddisseminatinginformationfromJavaobjects.ThissectionhighlightssomeoftheinputandoutputroutinesprovidedbythecoreJavacapabilitiesaswellastheSwingComponentsandAbstractWindowToolkit.Aswedelvefurtherintotherealmofnetworkedprogramming,wewilldiscoverthatmuchofwhatdrivesourdecisionsonanetworkedarchitecturewillbethatwhichisdetailedinthissection.Becauseinputandoutputarethemostimportantactionsacomputerprogramperforms,wemustdevelopastrongunderstandingoftheI/OcapabilitiesandlimitationsofJava.StreamsImagineyourgrandfatherfishinginastream.Heknowsthataslongashestaysthere,he'sgoingtogetabite.Somewhere,somehow,sometimeafishisgoingtocomedownthatstream,andyourgrandfatherisgoingtogetit.Justasyourgrandfatheristheconsumeroffish,yourapplicationsareeitherconsumersorprovidersofdata.InJava,allinputandoutputroutinesarehandledthroughstreams.Aninputstreamissimplyaflowofdata,justasyourgrandfather'sstreamisaflowoffish.Youcanwriteyourapplicationtofishfordataoutofyourinputstreamandeventuallytoproducedataaswell.Whenyourapplicationspitsoutinformation,itdoessothroughastream.Thistime,yourapplicationistheproducer,andtheconsumerisanotherapplicationordevicedowntheline.Javaprovidesseveraldifferentkindsofstreams,eachdesignedtohandleadifferentkindofdata.Thestandardinputandoutputstreamsformthebasisforalltheothers.InputStreamandOutputStreamarebothavailableforyoutouseasis,oryoucanderivemorecomplicatedstreamschemesfromthem.InordertocreatetheotherkindsofJavastreams,firstyoumustcreateanddefinethebasicstreams.Perhapsthemost-usedstreamformatsaretheDataInputStreamandtheDataOutputStream.Bothofthesestreamsenableyoutoreadorwriteprimitivedatatypes,givingyoutheflexibilitywithinyourapplicationtocontroltheresultsofyourapplication'sexecution.Withoutthiskindoffunctionality,youwouldhavetowritespecificbytesratherthanreadingspecificdata.Filebuffersareamethodcommonlyusedtoincreaseperformanceinaninput/outputscheme.BufferedInputStreamsandBufferedOutputStreamsreadinchunksofdata(thesizeofwhichyoucandefine)atatime.Whenyoureadfromorwritetothebufferedstreams,youareactuallyplayingwiththebuffer,nottheactualdatainthestream.Occasionally,youmustflushthebufferstomakesurethatallthedatainthebufferiscompletelyreadfromorwrittentothefilesystem.Sometimesyouwillwanttoexchangeinformationwithanotherapplicationusingastream.Inthiscase,youcansetupapipe.Apipeisatwo-waystream,sortof.The inputendofapipeinoneapplicationisdirectlyconnectedtotheoutputendofthesamepipeonanotherapplication.Ifyouwritetotheinputofthepipe,youwillreadthesameexactdataatthepipe'soutputend.AsyoucanseeinFigure1-3thisisaprettyniftywaytopromoteinterapplicationcommunication.Figure1-3.Pipesenableinteractionbetweentwoormoreapplications.Last,youwilleventuallywanttofiddlewithfilesonyourlocalfilesystem.TheFileInputStreamandFileOutputStreamenableyoutoopen,read,andwritefilesaswewillshowyouinamoment.RememberthatJavahasstrictrestrictionsonappletsecurity,somostfilestreamscanbemanipulatedonlybyapplications.Formoreinformation,consultChapter13,"JavaandSecurity."TheJavaCoreSystemInJava,applicationsareallowedtowritetothestandardoutputdevicesonamachine.IfyouuseaWebbrowsersuchasNetscape,thestandardoutputtowhichJavawritesisthe"JavaConsole"mentionedinoneofNavigator'swindows.IfyouwriteaJavaapplication(i.e.,astand-aloneapplet),thestandardoutputdeviceisthecommandlinefromwhichyouexecutetheprogram.TheSystemClassOneoftheclassesJavaincludesineveryappletorapplication,whetheryouspecifythatitdosoornot,istheSystemclass.TheSystemclassprovidessupportforinput/output(I/O)usingtheJavaconsole;youaretoprovidetheabilitytowritetotheconsole,readfromtheconsole,andwriteerrorstotheuser.TheJavaconsoleisprovidedintwoways,oneforbrowsersandoneforapplications.Inthebrowserenvironmenttheconsoleisaseparatebrowserwindowthathascontrolsforscrollingandclearing.Forapplicationsrunfromtheoperatingsystem(OS)commandline,theconsoleisthetextinterfaceyouseeandsuffersthesameproblemsasthetextbaseOSenvironment(lackofscrollingbackwards).TheJavaconsoleisreallyintendedtoprovidethesamelevelofuserinteractivityastheC++cin,cout,andcerrobjects.ThenamesofthestandardJavastreamsarein,out,anderr;thesenamescanbechangedusingtheSystemclassessetIn,setOut,andsetErrmethods.ChangingthenamesofthesestreamscanonlybedonebytheSecurityManager.InputUsingtheSystemClass InputintheSystemclassisactuallyhandledbytheInputStreamclasscontainedintheJavaI/Oroutines.System.inisanobjectoftypeInputStreamthatiscreated,maintained,andinitializedbytheSystemclass.Inotherwords,it'syoursforthetaking;youdon'thavetodoathingtouseit.TheInputStreamclassassumesthatyouwillbereadingfromthestandardinputstream(thekeyboardyouaresittingat).Astreamisasequenceofcharactersretrievedfromsomewhere.Thestandardinputstreamisthelocationthatyouroperatingsystemusestogetdatafromyou.Becausestreamsaredefinedascharactersfromasource,itisentirelyconceivablethatastreamcouldbeafile,amodem,amicrophone,orevenaconnectiontoanotherprocessrunningonyourcomputeroranothercomputer.Asamatteroffact,Javatreatsfilesandotherperipheralsasstreams.ThisabstractionofastreamsimplifiesI/OprogrammingbyreducingallI/Otoastream.So,howdoyougetinputfromtheuser?SimplyusetheSystemclass'sinputstreamtogettheinformationyourequire.Theinputstreamisanobjectwithseveralmethodstofacilitatedatainput.Forexample,thereareprimitive,yetuseful,routinestogetcharactersandstrings,toreadintegersandothernumbers,andeventogetastreamofunfilteredanduntranslatedbytes.Decidingwhichroutinetouseissimplyamatterofwhichkindofdatayouwishtoread.Inourexample,wewillreadandwritestrings:publicclassInputOutputTest(){Stringstr;//privatedatapublicvoidgetInput(){//readastringfromtheJavaconsolekeyboard(sysin)str=System.in.getln();}}OutputUsingtheSystemClassAswithinput,outputishandledthroughstreams.Howcanoutputbeastreamifastreamisasequenceofcharactersfromasource?Well,thesourceisyourapplication,andthestreamisroutedtoadeviceknownasthestandardoutput.Thestandardoutputisusuallyyourmonitor,butitcouldbeotherthingsaswell.Mostnotably,thestandardoutputissettobetheJavaconsolewhenanappletrunswithinNetscapeNavigator.Whenyourunthefollowingexamplefromwithinanapplet,watchyourJavaconsolefortheoutput.Ifyourunitfromwithinanapplication,theoutputshouldshowuponthecommandline.publicclassInputOutputTest(){Stringstr;//classdatapublicvoidgetInput(){//readastringfromthekeyboardstr=System.in.getln();} publicvoiddrawOutput(){//writeastringtotheconsolescreenSystem.out.println(str);}}FilesThestreamclasseswouldbeprettyuselessifyoucouldn'tmanipulatefilesaswell.ThereareseveralsecuritymechanismsdefinedinthesecuritymodelusedbyJava-capablebrowsersforrunningapplets.ThesemechanismspreventunguardedfileaccessandwillbediscussedinmoredepthinChapter13,"JavaandSecurity."Butfornow,simplyassumethataslongasyouarenotwritinganapplet,youwillbeabletomanipulatefiles.Inthepurestsense,standardinputandoutputarefiles.Assuch,theyaresometimessubjecttothesameappletsecurityrestrictions,sobeforewarned.TheBasicsWhenreadingandwritingtoandfromfiles,therearethreestepsthatmustbefollowed:1.Openthefileforreadingorwriting.2.Readorwritefromthefile.3.Closethefile.Itisimportanttodoeachstep.Failingtoopenafilewill,obviously,preventyoufromreading.Butperhapsnotasintuitively,youmuststillclosethefileoryoumaywreckyourfilesystem.Everyapplicationisallowedacertainnumberoffiledescriptors(handles)thatmaintainthestatusofafile.Ifyourunoutofavailablefiledescriptors,youwillnolongerbeabletoopenanyotherfiles.ThefollowingsnippetusestheFileReaderclasstoreadthecontentsofafilespecifiedonthecommandlineandthePrintWriterclasstowriteittotheJavaconsole:importjava.io.*;publicclassShowFile{publicstaticvoidmain(Stringargs[]){try{FileReaderfin=newFileReader(args[0]);PrintWriterconsoleOut=newPrintWriter(System.out,true);charc[]=newchar[512];intcount=0;while((count=fin.read(c))!=-1)consoleOut.write(c,0,count);consoleOut.flush();consoleOut.close();fin.close();}catch(FileNotFoundExceptione){System.out.println(e.toString());}catch(IOExceptione){System.out.println(e.toString()); }}Whenopeningafile,youhavethreeoptions.Youcanopenthefileforreadingsoyoucanextractdatafromit,butyouwillbepreventedfromwritingtothefileunlessyoucloseitandopenitforwriting.Youcanopenitforwriting,butyouwillbepreventedfromreadingfromit.Finally,youcanappendtoafile,whichissimilartowritingexceptthatitpreservesanydataalreadyinthefile.TakingFilesOneStepFurtherSowhatdofileshavetodowithnetworkedcomputing?Well,thediagraminFigure1-4offersagraphicalrepresentationofinputandoutputstreams.Rememberthatstreamsaremerelyinterfacestocollectionsofdata.Whatifthatdataislocatedonanetworkconnectionratherthaninaflatfileorakeyboard?Figure1-4.WithJava,yourinputoroutputneednotresideonthesamephysicalmachineonwhichyourapplicationisrunning.Thestandardinterfacetoanetworkinthecomputerworldisasocket.Asocketisaconnectionbetweenprocessesacrossanetwork.Theprocessescanbelocatedonthesamephysicalmachine,thesameLocalAreaNetwork,orevenacrosstheworldondifferentLANs.Thethreebasicstepsstillapply:1.Openaconnectiontotheremoteprocess.2.Readorwritedata.3.Closetheconnection.Again,aswithfilemanipulation,youcanusetheInputStreamandOutputStreamobjectstointerfacetothesocket.Infact,socketsarenothingbutfilesinthepurestsense.Theadvantagetothisfile-centrichierarchyisperhapsnotasobviousasitshouldbe.Intheend,allthreeformsofinputsourcesarecompletelyinterchangeable.Youshouldnotwriteyourapplicationstobespecifictoaspecifickindoffile.Inanobject-orienteddesign,theobjectsyoucreateshouldsimplyknowthattheywillhavetoreadorwritedatadowntheline.TheAbstractWindowToolkitandSwingClasses TheAWTisahalf-bakedattempttocreateauserinterfacetoolboxforprogrammers.Becauseallthevariousclasses,containers,andwidgetsinthetoolkitarecapableofbeingusedbothintheappletsembeddedinWebpagesandinthestand-aloneapplicationsonyourdesktop,itisapowerfullyextensibletool.Attheheartofthiskindofflexibilityistheideathatthetoolkitisanabstraction—inotherwords,alayerontopofyourcurrentwindowingsystem.Thisabstractionismoreunderstandableifyouknowthebackgroundbehindit.WhenSunwascourtingitsearlycustomers,NetscapeinsistedthattheJavaVirtualMachine(JVM)includedinitsbrowsermustcreatewidgetsthathadtheexactlookandfeelofthehostoperatingsystem'swidgets.Since"Swing"wasn'tyetagleaminitsfather'seye,theonlywaytoaccomplishthiswastousethepeercomponentsofthehostoperatingsystem.ThuswecantrulysaythattheAWTisanabstractionofthewindowingsystemoftheoperatingsystem.YourcurrentwindowingsystemmaybeanythingfromX11/MotiftoWindows95'sownwindowsystem.Inanyevent,theAWTensuresthatnativecallsaremadetothesewindowingsystemsinordertoallowapplicationstorunontopofthedesktop.ForappletswithinaWebpage,thebrowsermanufactureressentiallycreatesawindowingsystemthatrenderstheAWT'swidgetswithinitself.TheendresultofallthisisthateventuallyanativecallismadeforeachactiontakenbytheAWT.Yourapplicationsneednotbeawareofthis,forJava'splatformindependenceensuresthat,nomattertheplatformonwhichyouexecutebytecodes,theresultswillbeidentical.Oneoftheproblemswiththisapproachtouserinterface(UI)implementationisthatwhenmakingaUIthatmustberenderedthesamewayonalltheplatformsitistobetargetedto,smalldifferencesinthewaythatcomponentsarerenderedoneachofthetargetedsystemsmaycausetheoveralleffecttohaveproblems.Forinstance,aUIhavingseveralcloselyalignedtextfieldsmaylookgoodonWindowsplatformsbutappearoverlayedonUNIXmachines.OneofthemajorcomplaintsabouttheAWTbypeopleusedtobuildinguserinterfacesforenterpriseapplicationswasthatithadarelativelysmallsetofwidgetsandlowfunctionality.AWTprovidedonlyslightlymorefunctionalitythanthewidgetsprovidedinHTML'sformscontrols.Inearly1997theworkonJDK1.1incorporatedanumberofnewpiecesincludingNetscapeCorporation'sInternetFoundationClasses(IFC),componentsfromIBM'sTaligentDivision,andLighthouseDesign.ThefirstreleaseofSwing1.0inearly1998containedalmost250classesand80interfaces.Theartofuserinterfacecreationhadbeenraisedtoanewlevelandwasnowabletogoheadtoheadwithplatform-specificdevelopmenttools.TheJava1.2platformprovidesasetofcomponents(Swing)thateliminatethisproblembyeliminatingtheuseofpeercomponents.TheSwingcomponentsarepureJavaandwillrenderreliablyonallhostplatforms.WithSwingthenativelookandfeelofWindows,Motif,orMacwidgetsareoptionsfromapredefinedlistoflookandfeelsthatareextensiblebytheuser.InputAlternatives TheAWTandSwingcontainwidgetsdesignedtoelicitresponsefromtheuser.Fromsimpletextareastomorecomplexdialogboxes,eachoneisdesignedtofunnelinformationfromtheuser'skeyboardtoyourapplication.Mostofthemareveryeasytouseandprogram,sowe'llleaveittotheseveralJavabooksonthemarkettoprovideyouwithareferenceandabasiclistandexplanationoftheelementsthatareincluded.Rememberthatinputinawindowingsystemisnotlimitedtotypingwordsonthescreen.Everypushbutton,checkbox,orscrollbareventisaformofinputthatyoumayormaynotchoosetodealwith.EveryAWTclasshassomewayoranotherofcheckingthestatusofitsinputmechanism.Forexample,yourscrollbarwillbeabletotellyouifithasbeenmoved.Youmaychoosethentotakesomeaction,orlettheAWTdoitforyou.ThereisnoneedtoimplementscrollingtextforascrollbarwhentheAWTisfullycapableofdoingit.OutputAlternativesObviously,theeasiestwaytodisplayoutputwiththeAWTistodisplaysomethinggraphically.TheAWTsupportssimplegraphicsroutinesfordrawing,aswellasfortheusualsuiteoflabels,multimedia,andwidgetmanipulation.OutputissignificantlyeasierusingtheAWT.Withoutthetoolkit,youwouldhavetomanagenotonlywhattodowiththeinputyoureceive,butalsohowtodisplayyourresponse.I/OinShortInputandoutputareattheheartofeveryprogramyoucreate.Nomatterwhattheobjectiveofyourapplication,somehowyouwillneedeithertogetaresponsefromtheuser,todisplayaresponse,ormaybeevenboth.Totakethingsonestepfarther,yourinputoroutputneednotresideonthesamephysicalmachineasthatonwhichyourapplicationisrunning.Indeed,thatistheverysubjectofthisbook.Bystretchingyourapplicationstofitanetworkedmodel,youwillbeabletotakefulladvantageoftheinputandoutputschemesofferedtoyoubyJava.Whenyourapplicationsreceiveseveralinputs,theywilloftengetinundatedwithprocessing.Toalleviatethis,Javaprovidesafullsuiteofthreadingutilities,whichwediscussinthenextsection.Threadsallowyourapplicationstoexecutestepsinparallel.So,whenyourapplicationreceivestwodifferentinputssimultaneously,youcanusethreadstosimultaneouslyresolvethemandproduceoutput.IntroductiontoThreadinginJavaMultithreaded(MT)programsarethecurrentrageincomputerscience.Booksuponbooksuponbookshavebeenwrittenthatdescribethebenefitsofthreading,thethreadingfeaturesinherentinvariousoperatingsystems,andthevariousformsofthreadedarchitectures.So,whatoneartharethreads?Howcanyouusetheminyourprograms?Willthreadingcontinuetoworkinthoseapplicationsthatrunnativeonoperatingsystemsthatdonotsupportthreading?WhatdoesitmeantobeMT-safe,andhowdoyoudesignanMT-safeprogram? Theentirerealmofmultithreadedandmultitaskedprogrammingtranscendsthescopeofthisbook.Wewillconferthatknowledgeofthetopicthatisdirectlyrelatedtotheideasofnetworkedprogrammingand,incaseswheremoreresearchmaybewarranted,directyoutotheappropriateresources.WhatAreThreads?Let'ssayyou'resittinginyourlivingroomwatchinganotherWashingtonRedskinsvictory.YougetboredwatchingthemassacreoftheDallasCowboys,andyoudecidethatyouwouldliketoseethe49ersgameinprogress.Inthegoodolddays,youwouldhavetoactuallyswitchchannelsandchoosebetweenoneortheother.But,thesedays,televisionshavePicture-in-Picture(PIP)capability.BypressingthePIPbuttononyourtrustyremotecontrol,youcanwatchtheRedskinsdemolishtheCowboysonalittleboxinthecorneroftheTVwhilewatchingthe49ersontherestofthescreen.Thisisaprimeexampleofmultithreadedprogramming.Thelittlescreenandthebigscreenshareresources(inthiscase,theareaofthefulltelevisionscreen),buttheyarenotabletoaffectoneanother.Intheareasinwhichthetwogamescollide,onescreengiveswaytoanother.ThreadsinYourComputerInthecomputerworld,multithreadedapplicationsexistsimilarlytothoseinthetelevisionworld.Theysharethesamearea,inourcasethetelevisionscreen,inrealitythephysicalprocessinwhichtheapplicationresidesandispermittedtoexecute.Multithreadedapplicationsareabletoexecuteindependentpiecesofcodesimultaneously.Eachoftheseindependentlyexecutingpiecesofcodeisknownasathread.Threadsareimplementeddifferentlybydifferentoperatingsystems.InSolaris,forexample,threadsaredefinedandmaintainedintheuserenvironment.Theoperatingsystemmaintainsresponsibilityovertheprocess,regardlessofwhattheprocessdecidestodowithitself.Inasense,theoperatingsystemtreatstheprocessasanobject.TheOSonlycaresabouttheinterfacetotheprocess,orhowitstartsup,shutsdown,beginsexecution,andperformssimilaroperations.Ithasnofeelingswhatsoeverabouthowtheprocesshandlesinformation.Infact,thisisthefundamentalconceptofthreads.Threadsexistasauser-createdanduser-managedaspectofaprogram.Theoperatingsystemcouldcarelessiftherearemultiplethreadsintheexecutableorifitissinglethreaded.Furthermore,theoperatingsystemwillnothelpyouresolveconflicts.Allitcaresaboutistheintegrityoftheprocess,notaboutwhatgoesoninsideit.HandlingConflictsLet'ssayyouhaveacoupleofthreadsprancingalongmerrilywithinyourapplication.Suddenly,theybothaccessthesamepieceofdataatthesametime.Thisresultsinwhatisknownasconcurrentaccess.Concurrentaccesserrorsoccurasaresultofpoorthreadmanagementonthepartofthemainapplication. Accesserrorsoccurineverydaylife,too.Let'ssayyou'vescheduledanappointmentfromeleveninthemorningtooneintheafternoon.Carelessly,youforgotyourall-importantstaffmeetingattwelve-thirty.Obviously,youcan'tbeintwoplacesatonce!Theendresultisthatyou'veplacedyourselfintwomeetings.Thethreadswithinourapplicationssimilarlyhaveaccessedidenticaldataatthesametime.Whencreatingathread,thefirstthingyoumustdetermineiswhatdatathatthreadwilltouch.Youthenhavetofenceoffthatdatasothatonlyonepossiblethreadcanevertouchitatanygivenmoment.InSolaris,thisisdonewithaconceptcalledmutualexclusion.Amutualexclusionlockplacedaroundyourdataensuresthatitwillneverbepermittedtoenteraconcurrentaccesssituation.ImaginearelayteamoffourpeoplecompetingattheupcomingOlympics.Thefirstrunnerontherelayteamisgivenabatonthatmustbepassedtoateammatebeforethatteammateisallowedtorun.Iftheteammaterunswithoutthebaton,sheisdisqualified.However,ifthebatonispassedproperly,therunnercancontinueuntilshearrivesatthefinishlineormustpassthebatontoanotherteammate.Likewise,differentthreadscanobtainthelockaroundthedatasolongasthelockisavailable.Ifthelockisunavailable,thethreadmustwait,effectivelysuspendingitself,untilthelockisavailable.Therearespecificsettingstoallowthreadstocontinuewithoutwaiting,butthesesettingsarebeyondthescopeofthisbook.Ifonethreadgrabsalockbutneverletsgo,thenitwillhavedeadlockedtheentireapplication.Whenyourmethodsobtainathread,makesurethattheygiveitupsomehow.Otherwise,therestofyourapplicationwillwaitforalockthatwillnevercomefree.Formoreinformationonthreads,consulttheexcellentSunMicrosystemstitle,ThreadsPrimerbyBillLewisandDanielJ.Berg.ThreadinginJavaCreatinganddebuggingthreadsinJavaisconsiderablysimplerthandoingsoinC++.DeadlocksinJavaaremucheasiertoprevent,andatonmoreintuitive.ButmultithreadedapplicationsinJavaarenotasrobustoraspowerfulastheirC++counterparts.Inshort,therearetradeoffstothreadinginJava,foritisnotanall-encompassinganswertothemultithreadingquestion.WhatthreadsinJavadoisprovideyou,theapplicationprogrammer,withaconsistentinterfacetothethreadsoftheunderlyinghostenvironment.Anythingthatmaybe"quirky"inthethreadsofthehostingoperatingsystemwillstillbethere.ThisconsistencyofAPIisimportantasourtargetenvironmentisanyplatformthatthereisaJVMwrittenfor,andtheconsistencyhelpsmakeourcodemoreportableandreusable.Javatreatsthreadsasuser-levelentitiesaswell.AJavaappletorapplicationrunswithinaprocessspacedefinedintheJavaVirtualMachine.TheJVMallocatesprocessesandtheresourcesforeachprocessandallowstheappletorapplicationtodefinehowthatprocessspaceisused.JavaprogramsthatimplementthreadsmustdosousingtheThreadclassoraderivativethereof. TheThreadClassJava'slanguagehierarchy,whichincludesthelikesofStrings,Integers,andsoon,alsocontainsapowerful,yetincrediblysimpleThreadobjectthatyoucanimplementwithinyourprograms.TheThreadclassprovidesallthefunctionalitynecessaryforyoutocreatefullymultithreadedandMT-safeapplicationsusingtheJavalanguage.NOTETwoapproachestospawningthreadsinJavaareworthnoting,asoutlinedinthefollowingsections.Manyofournetworkingexampleslateronwillmakeheavyuseofoneortheothermethod.Asalways,therearetradeoffsandbenefitsforeacharchitecturaldecisionyoumake.UsingtheEntireClassAsaThreadThefirstmethodwecouldemployinvolvesspawningthreadsinwhichanentireclasscanreside.Forexample,wespawnathreadandthencreatearunnableclassandattachittothethread.Nowtheentireclassexistswithinthethreadandthestreamofexecutionforthatclassismaintainedbythethread.Ifthethreadisdestroyed,thestreamofexecutionislikewisedestroyed.Thebiggestadvantagetothismethodisthattheclassneednotknowanythingabouthowitistobeimplemented.Takealookatthefollowingexample:publicclassAnimatorextendsPanelimplementsRunnable{Animator(){…}publicvoidrun(){…}}publicclassAnimatorManager{Animatoranimations[];ThreadanimationThreads[];AnimatorManager(){…}publicvoidcreateAnimation(Animatoranim){//firstspawnathreadfortheclass//nowletthethreadcontinue…}}TheAnimatorManagerclassisresponsibleforcreatingaseriesofAnimatorobjects,spawningathreadfortheobjecttoexecuteinandshuttingdown,suspending, resuming,orinquiringaboutthestatusofthethread.NotehowtheAnimatordoesnotknoworcarewhetheritwillbeinathreadofexecutionorinanentireprocess.Itisarunnableclass,meaningthatwhateveriscontainedwithintherunfunctionwillbeexecutediftheparentprocessorthreadallows.Theobjectiscreatednormally,andourAnimatorManagerassumesthattheobjectisalreadycreated.TheThreadiscreated,buttheobjectispassedtoitasaparameter.ThecorrespondingconstructorintheThreadclassknowsthattherunnableobjectwillresidesolelywithinitsthreadofcontrol.publicclassAnimatorManager{Animatoranimations[];ThreadanimationThreads[];AnimatorManager(){…}publicvoidcreateAnimation(Animatoranim){//firstspawnathreadfortheclassanimationThreads[currentThreadCount]=newThread(anim);//nowletthethreadcontinue…animationThreads[currentThreadCount].start();}}NOTERememberthatJavaisinherentlyobject-oriented,sothiskindofthreadcreationisquitewithinthereachofthelanguage.Thereisnofunnybusinessgoingonhere.Athreadiscreatedandanobjectistoldtolivewithinit.Itisactuallyquiteintuitiveinanobject-orientedsense.Thenextmethodhearkensbacktothedaysofstructuredprogramming.InheritingfromtheThreadClassThesecondwaytoimplementthreadsistocreateaclassthatinheritsfromtheThreadclass.Inthefirstmethod,wecreatedanobjectthatwasafree-standingobjectinitsownright.Inthiscase,wewillcreateanobjectthatisaThreadobjectfromthebeginning.Inessence,theJVMtreatsbothmethodsassimilarandreasonablemeanstospawningthreadedobjects,andbothareacceptablefromastyleperspective.InheritingfromtheThreadclassisactuallyquitesimple.InsteadofextendingfromPanelorApplet,yourclasssimplyextendsfromThread.Inyourinitmethodorconstructor,youmustinitializethethreadaswell.Obviously,yourclassmustbeawarethatitisrunninginathread. ThethreadcodeforaclassthatinheritsfromThreadisintheRunmethod.AsinaclassthatimplementsRunnable,inheritingfromThreadautomaticallyenablesyoutoimplementtherunmethod.Anycodeyouwanttomanagethethreadshouldbeplacedthere.Ifyouneedtomakethethreadsleeporsuspend,that'swhereyoushouldplaceit.Thedifference,however,betweenextendingThreadandimplementingRunnableisthatwhenyouinheritfromThread,yourentireclassisathread.Thethreadmustbestartedandstoppedfromwithintheclass,unliketheothermethodinwhichthethreadcontrolsareoutsidetheclassitself(seeFigure1-5).Figure1-5.Threadcontrolsareaccessedfromdifferentlocationsdependingonthemethodchosen.Takealookatthefollowingexample,andnoticehowtheconstructorcallsthestartmethodorthethread:publicclassAnimatorextendsThread{Animator(){start();}publicvoidrun(){…}}Asyoucansee,theclassisclearlyathreadedclass.Whathappensifyouwanttousetheclass'smethodologywithoutusingthreads?You'llhavetocreateanewclassthatdoesn'tusethreads,oryou'llhavetoreverttothefirstmethod.ImplementingRunnableandplacingyourthreadcontrolsoutsidethetargetclassisthepreferredwayofusingthreads,butinheritingfromthreadscanbeparticularlyusefulforhighlymodularcodeinwhichyouwanttopackageanentireobjectthatdoesnotrelyonanythingelse. ThreadControlsAthreadhasseveralcontrolmethodsthataffectitsbehavior.Simplystartingandstoppingathread'sexecutionarebuttwoofthemanytoolsavailabletoyoutomanipulatehowprogramsexecute.Forexample,onseveraloccasions,youwillwanttopauseathread'sexecution,andeventuallyresumeit.TheThreadclassoffersusarichsetofmethodsforcontrollingthreads:1.start2.stop3.suspend(deprecatedinJDK1.2)4.resume(deprecatedinJDK1.2)5.sleep6.destroy7.yield8.join9.run10.isAliveThestartmethoddoesexactlywhatitsays.Ittellsthethreadthatitmaybeginexecutionofallthestepscontainedintherunmethod.Therunmethoditselfmaycallanyoftheprecedingthreadcontrols,butobviouslyyouwillwanttorestartthethreadsomewhereiftherunmethoddecidestosuspendit!Thestoproutineterminatesthethreadandpreventstherunmethodfromexecutinganyfurthersteps.Itdoesnot,however,shutdownanysubthreadsthatitmayhavecreated.Youmustbecarefulandmakesurethateverythreadyoucreateeventuallyeitherterminatesonitsownoristerminatedbyitsparent.Otherwise,youcouldverywellhaveseveralthreadsexecutingandconsumingresourceslongaftertheappletorapplicationhasterminated.Thesuspendandresumeroutinesareprettyself-explanatory.Whensuspendiscalled,thethreadceasesexecutionofitsrunmethoduntilresumeiscalledsomewheredowntheline.Ifyourparentthreadneedstoinquireaboutthecurrentrunningstatusofathread,itmaycalltheisAlivemethodandfindoutifthethreadisstopped.Obviously,ifthethreadisn'tstopped,anditisn'trunning,itmustbesuspended.Note,inJDK1.2suspendandresumearedeprecatedduetoproblemswithdeadlocksituationoccurring.Whenathreadhaslockedasystemresourceandisthensuspended,otherthreadscannotaccesstheresourceuntilthesuspendisresumed.Ifthethreadthatissupposedtodotheresumefirsttriestolocktheresource,adeadlockoccurs.Thejoinmethodcausesthecurrentlyexecutingthreadtowaituntilithasstopped;thecurrentthreadthenblocksuntil:1.Thecurrentlyexecutingthreadisinterrupted.2.Thecurrentlyexecutingthreadisterminated.3.Thespecifiedtimeouthasexpired;ifatimeisnotspecified,thethreadwillwaitindefinitely. Last,thesleepmethodtellsthethreadtopauseforagivennumberofmilliseconds.Itisparticularlyusefulfortheclockbecausewewantitto"tick"everysecond.ThestatediagraminFigure1-6shouldmakeclearthethreadtimingyouneedtobeawareof.Rememberthat,beforeanythingcanbedonetoathread,youmustcallstartonit.Onceyouarefinishedwiththethreadofexecution,youmustcallstop.Figure1-6.Thecontrolmethodsthataffectathread'sbehaviour.SynchronizedMethodsConflicthandlingwithinJavaisimplementedusingmethodsynchronization.Ifyouhavedatathatcouldpotentiallydeadlockbetweentwothreads,thenyoumustdeclarethefunctionsinwhichthedataismodifiedassynchronized.Javapreventsmultiplethreadsfromenteringthesynchronizedmethodsandtherebyeliminatesthepossibilityofdeadlock.Creatingasynchronizedmethodisactuallyquiteeasy.Itissimplyamatterofdeclaringthatthefunctionwillbesynchronizedinthemethodsignature,ascanbeseeninthefollowingsnippet.publicclassThreadClass{intdata;…publicvoidsynchronizedaddToData(intaddend){ data+=addend;}…}Thereareacoupleofimportantcaveatstosynchronizedfunctions.Becausemultiplethreadsmayrequireentrytoasynchronizedfunction,itisbettertokeepanyfunctionthatisdeclaredassynchronizedshortandsweet.Whenonethreadentersasynchronizedfunction,keepingitstimespentinthefunctiontoaminimumwillkeepyourprogramsrunningsmoothly.Afterall,theideabehindthreadingistogetyourprogramstoexecutestepsinparallel,nottospawnthreadsthatendupwaitingforeverforeachothertofinishwiththedata.yield(),wait(),andnotify()Inanapplicationwithmultiplethreads,oftenyouwillhavemanythreadscompetingwithoneanotherforresources.Onewaytoallocatethoseresourceseffectivelyistosettherelativeprioritiesofeachthread.Wewilldiscussthatinamoment,butrightnowlet'sdiscusssomeofthespecificstepsyoucantakewithinthethreaditself.Rememberthatwhenthreadsexecute,theyallsharethesameprocessspaceinwhichtheapplicationresides.Likeabunchofkidsforcedtoshareatoy,thethreadscompeteandvieforcontroloftheprocess.Likeanygoodparent,however,youhaveseveraltoolsatyourdisposaltomakesurethethreadscooperate.Sometimesyouwillwanttocontrolentryintoafunctionandlabelthefunctionassynchronized.Eventhoughthefunctionislong,youwanttoyieldcontrolofthefunctionprettyearlyon.Youcancallthenotifymethodtotelltheparentthreadthatyouarefinishedwiththesynchronizedlock.Inordertomakeathreadstandbyforanotifymessage,youmustaddthewaitmethodtothethread'sexecutionroutines.Thenotifymethodiscalledsomewhereinanexecutingthread.Oncenotifyiscalled,anythreadawaitingexecutiononawaitcallautomaticallyproceeds.Anotherwaytogiveuptheprocessspaceinwhichathreadrunsistocalltheyieldroutinespecifically.Whenyieldiscalledwithinathread,thethreadgivesupanyschedulingpriority,processspace,orclaimtoitscurrentturninthesharingcycle.ThreadPrioritiesTIPAmoreelegant,yetmoreconfusing,waytocontrolthreadsisbysettingtheirpriority.Obviously,whenyousetathreadtohaveahighpriority,itgetsfirstcrackatanyprocessingtimeandresources.Youshouldbecarefulandjudiciousinsettingthreadpriorities.Evenwiththebestofintentions,youcouldverywelldefeatthepurposeofusingthreadstobeginwithshouldyouseteverythreadatahighpriority. InJava,threadsmayhaveoneofthreepriorities:minimum,normal,andmaximum.YoumaysetthepriorityusingthesetPrioritymethodoftheThreadclassandretrievethepriorityofanythreadbyusingthegetPrioritymethod,likeso:ThreadthreadOne;ThreadthreadTwo;ThreadthreadThree;threadOne.setPriority(Thread.MIN_PRIORITY);threadTwo.setPriority(Thread.NORM_PRIORITY);threadThree.setPriority(Thread.MAX_PRIORITY);BecausethreadsareapowerfulandunderusedaspectofmostJavaprograms,threadschedulingandprioritizingisaflexibleandequallypowerfulwaytocontrolhowyourapplicationsbehaveandexecute.DaemonThreadsTherearetwokindsofthreads.Sofarwehavediscussedapplicationthreads,whicharetiedtotheprocessanddirectlycontributetotherunningoftheapplication.Daemonthreads,ontheotherhand,areusedforbackgroundtasksthathappeneverysooftenwithinathread'sexecution.Normally,anapplicationwillrununtilallthethreadshavefinishedtheirexecution.However,iftheonlyremainingthreadsaredaemonthreads,theapplicationwillexitanyway.Javaitselfhasseveraldaemonthreadsrunninginthebackgroundofeveryapplication.Java'sgarbagecollectioniscontrolledbydaemonthreadsknownincomputerscienceparlanceasreaperthreads,orthreadsthatrunthroughanapplicationlookingfordeadweight.Inthegarbagecollectionthread'scase,thedeadweighthappenstobeunusedbutallocatedmemory.Ifyourapplicationneedstosetupadaemonthread,simplycallthesetDaemonmethodofthethread,asshowninthefollowingsnippet.Theapplicationinwhichthethreadresideswillknowtoignorethatthreadifitneedstoexecute,andprogramexecutionwillcontinuenormally.Threadt=newThread(myClass);t.setDaemon(true);ThreadSummaryThreadsareonewayinwhichyoucanaffectthebehaviorofanobject.Serializationisanother.Serializationallowsyoutostoreyourobjectsasstrings.Whenweusethreads,wedosotochangehowitbehaveswhenitisrunning.Serializationdoesnotallowustopreservethatruntimebehavior,onlytheclass'sstaticbehaviorandcharacteristics.Wheneveryoureconstructaserializedclass,onlyyourclasswillbereconstituted correctly,notanyofthethreads.Therefore,itisimportantthatyourthreadsbeasobject-orientedaspossiblesothattheycanstoretheirstatewhennecessary.ObjectSerializationSerializationisaconceptthatenablesyoutostoreandretrieveobjects,aswellastosendfull-fledgedobjects"overthewire"tootherapplications.ThereasonserializationisofsuchvitalimportancetoJavashouldbeclear:withoutit,distributedapplicationswouldnotbeabletosendobjectstoeachother.Thatmeansthatonlysimpletypessuchasintandcharwouldbeallowedinparametersignatures,andcomplexobjectswouldbelimitedinwhattheycoulddo.It'ssortoflikesayingyouwouldhavetotalklikea3-year-oldwheneveryouspokewithyourboss.Youwanttohaveacomplexconversation,butyouarelimitedinwhatyoucansay.WhatIsSerialization?Withoutsomeformofobjectstorage,Javaobjectscanonlybetransient.Therewouldbenowaytomaintainapersistentstateinanobjectfromoneinvocationtoanother.However,serializationcanbeusedformorepurposesthanmaintainingpersistence.TheRMIsystemusesobjectserializationtoconvertobjectstoaformthatcanbesentoveracommunicationmechanism.Whenanobjectisserialized,itisconvertedtoastreamofcharacters.Thosecharacterscanbesentoverthewiretoanotherlocation.Parameterspassedinremoteobjectsareautomaticallytranslatedintoserializedrepresentation.Onceanobjectisserialized,itcanbesafelysentviaacommunicationmethodtoaremotelocation.TheserializationroutineshavebeenincorporatedintothestandardJavaObjectclasswithseveralroutinestofacilitatethewritingandreadingofasecuredrepresentation.Thereareseveralsecurityconcernsthatyoumustbeawareof,andwewilldiscussthoseinamoment.Withoutobjectserialization,JavacouldnevertrulybeaneffectiveInternetlanguage.HandlingObjectRelationshipsAnimportantconsiderationoftheobjectserializationfacilitiesisthattheentireprocessisexecutedinamannertransparenttoanyAPIsoruserintervention.Inotherwords,youneednotwriteanycodetoutilizeserializationroutines.Whenwritinganobject,theserializationroutinesmustbesuretodosoinamannerthatallowsfullreconstructionoftheobjectatalatertime.Notonlymusttheclassstructurebesaved,butthevaluesofeachmemberofthestructuremustbesavedaswell.Ifyouhadaclasswiththefollowingrepresentation:publicclassCuteBrownBear{ColoreyeColor;floatheightInches;floatweightPounds;} ItmustbesavedsothatthevaluesofeyeColor,heightInches,andweightPoundsarepreservedandcanberestoredoncethereadingfunctionsareinvoked.Sometimes,however,thingscanbecomecomplicatedwhenobjectsbegintorefertooneanother.Forexample,thefollowingclasscontainsCuteBrownBearaswellasseveralothertoyobjectsthatwemustsaveaswell:publicclassToyBox{CuteBrownBearbearArray[5];ActionFigureactionFigureArray[5];}TheserializationroutinesmustnotonlyserializetheToyBoxobject,buttheCuteBrownBearobjectsandActionFigureobjectsaswell.Tohandlethiskindofsituation,theserializationroutinestraversetheobjectsitisaskedtowriteorread.Asittraversesanobjectrepresentation,itserializesanynewobjectsautomatically.If,downtheline,itfindsanotherobjectofatypealreadyserialized,itmerelymodifiestheearlierserializedrepresentationtorefertothenewinstance.Inthismanner,serializedobjectsarecompactandefficientwithoutmuchduplicatedcode.Forexample,whenweneedtoserializetheToyBoxobject,theserializationroutinesfirstserializeCuteBrownBearinarraypositionone.Arraypositionstwothroughfivearenotserializedontheirown;rathertheoriginalserializedrepresentationismodifiedtopointtotheirlocationsandvalues.So,thefinalserializedobjecthasonereferencetotheCuteBrownBearobject,plusfivesetsofdatavalues.TheOutputStreamsSerializationoutputishandledthroughtheObjectOutputStream.SerializationcallsrefertothewriteObjectmethodcontainedwithinthestream,passingittheinstanceoftheobjecttobeserialized.Thestreamfirstcheckstoseewhetheranotherinstanceofthesameobjecttypehasbeenpreviouslyserialized.Ifithas,theroutineshandleitaswediscussedintheprevioussection,merelyplacingthenewvaluesalongsidetherepresentation.If,however,theobjecthasyettobeserialized,theroutinescreateanewserializedrepresentationandplacethevaluesnexttoit.Mostserializationishandledtransparently.ButanobjectmayatanytimebegintohandleitsownserializationbyreimplementingthewriteObjectmethod.ThewriteObjectmethodispartofeveryObjectclassandcanbeoverriddenoncommand.Ifyouneedafinergrainedserializedrepresentation,orwouldliketoincludesomekindofencryptionorothertechniquebetweenserializationendpoints,thisiswhereandhowyoudoit.Asanexample,letusinstantiateaCuteBrownBearobjectandserializeit://createthestreamshere... FileOutputStreamfileOut=newFileOutputStream("filename");ObjectOutputStreamobjectOut=newObjectOutputStream(fileOut);//instantiatethenewbearobjectCuteBrownBearbear=newCuteBrownBear();//serializethebearobjectOut.writeObject(bear);HandlingObjectWebsAnobjectwebisacomplexrelationshipbetweentwoormoreobjectsinwhichobjectsrefertootherobjectsthatmayeventuallyreferbacktoit.Ifyouweretoserializesuchanobjectrepresentation,youcouldpotentiallybecaughtinaninfiniteloop.Let'ssaywehadasystemofroadsbetweenthreecities,Seattle,Washington,DC,andSanFrancisco.Wewanttotakeanend-of-summerroadtripandvisiteachcity.Theonlyinstructiontheautoassociationgaveuswas"ifyouhitoneofthesethreeroads,followituntilitends."Followingthatlogic,wewouldstartatSanFrancisco,gotoSeattle,visittheRedskins,comebacktotheGoldenGate,andgotoSeattle,andsoon(seeFigure1-7).Figure1-7.Anexampleofserializationinwhichyouneedtostoreobjectsthatarelinkedbyacircuitousroute.Likewise,ifweweretoserializeSanFrancisco,thenSeattle,followedbyWashington,DC,andkeepfollowingthepathbacktoSanFrancisco,wewouldendupfollowingthesameloopaninfinitenumberoftimes.Thislatticearrangementensuresthatasimpletree-basedalgorithmwillnotsuffice.Java'sobjectserializationroutineaccountsforthiskindofstructureinthesamemannerthatithandlesmultipleobjectsofthesametypeinthesamestream.Becauseoftheseobjectwebs,anyserializationmusttakeintoaccountthoseobjectsthathavealreadybeenserialized.So,inadditiontotheserializationmethods,Java'sobjectserializationroutinesalsokeeptrackoftheobject'sserializedstate.Moreover,Javaalsokeepstrackofwhetherobjecttypeshavebeenserializedaswell.Insodoing,itcankeeptrackofthedatacontainedintheobject,nottheentireobjectitself. ReadingObjectsReadingobjectsisamatteroftakingtheserializedrepresentationandreversingtheprocessthatcreatedtheminthefirstplace.Remembertohandleyourdeserializationinthesameorderasyourserialization,traversinganytreesinasimilarfashion.Theobjectiveistoreconstructtheoriginalobject.ThedeserializationroutinesarehandledwithacorrespondingObjectInputStreamandthereadObjectmethodcontainedtherein.Onceagain,toobtaincontroloverserializationroutinesforyourobject,youneedtooverrideandreimplementthewriteObjectandreadObjectroutines.SecurityandFingerprintingSometimesobjectscanbeserializedsurreptitiouslybyotherobjectslinkedinbyyourapplication.Ifyourobjectdoesthingsthatyouwouldprefertokeepprivateandunknowntotheworld,thenyouneedtodisableyourobjects.Serializationcanbedisabledforanobjectbyaddingtheprivatetransienttagtotheclassdefinition:privatetransientclassCuteBrownBear{...}OrtheobjectitselfcanoverridetheserializationroutinesandreturnaNoAccessException.TheNoAccessExceptiontellsanyobjectthatattemptstoserializeyourimplementationthatitmaynotdoso.Furthermore,itgivesasufficientdebuggingwarningtoanyapplicationsthatmayreuseyourobject.publicclassCuteBrownBear{...therestoftheCuteBrownBearclassgoeshere...publicvoidwriteObject(...)throwsNoAccessException{}publicvoidreadObject(...)throwsNoAccessException{}}SerializationOverviewJavaautomaticallyhandlesitsownobjectserializationforyou.However,ifyouaresoinclined,youmayreimplementtheserializationroutineswithinyourownobjects.Wehavepresentedyouwithseveralserializationconcernsinthischapter.Ifyouaregoingtohandletheserializationforagivenobject,makesureyouconformtothevarious restrictionswehavegivenyou.Ifyourobjectsdonothandletheirserializationproperly,yourentireobjectsystemmaynotbeserializable.YetanotherissueofimportancetoJavaprogrammersisperformance.Whileserializationensuresthatourobjectscanbesavedandrestored,performanceissuesstrikeattheverylimitationsofthelanguage.Thegreatestprogrammersintheworldcanbuildtheapplicationsseenonlyinsciencefiction,buttheyarepreventedfromdoingsobylimitationsintheirhardwareandthespeedwithwhichtheirsoftwarecanberun.PerformancePerformanceissuesaretheprimaryreasonwhymostmajorcorporationshavenotyetbegunwholesalerevisionsoftheirexistingcomputersystemstousetheJavalanguage.AlthoughmanyoftheseissuesarerealandJavahasyettobecometheperfectlanguageinallrespects,itisnotnecessarilytruethatperformanceisamajorshow-stopper.Often,theperceptionisnotreality.PerformanceIssuesWhenwespeakofperformanceinJava,weareactuallyspeakingoftwoverydifferentproblems.Thefirstisthedownloadperformanceofanapplet.Today,yourhard-coreappletswilloftencontainupwardsof20to30classes.IncorporateamechanismsuchasJavaIDLorJavaRMI,andthecommunicationinfrastructuremayaddupto100differentclassesofitsown.Inorderfortheapplettorun,eachofthoseclassesmustbedownloadedinordertobeused.Thesecondmajorissuebehindperformanceisruntimeperformance.Forbothappletsandapplications,thespeedwithwhichJavacomputesisprettyslow.ComparedtocomparablestatisticsforsimilarapplicationswritteninC++,Javadoesnotmeasureup.Thereareseveralinitiativesandtechnologiesbecomingavailablethatmayrenderthatissuemoot.DownloadPerformanceForappletwriters,downloadperformanceisthesinglemostimportanthurdletoovercome.Whilemostprogrammerscancreatetrulyartisticprogramsthatcanaccomplishawidevarietyofthings,theyoftenmeetabrickwallwhentheircustomertriestodownloadthemwithinabrowser.Inordertostudythedownloadperformanceofanapplet,wemustfirstdiscusshowanappletisdownloadedtobeginwith.Javaincorporatesanobjectcalledtheclassloader.Theclassloaderlocatestheclasstobedownloaded,goesaboutfetchingit,andrecognizesanyotherdependentobjectsanddownloadsthoseaswell.Thebrowserdoestheactualdownloadingandtheclassloadermerelytellsitwhattodo.Whenthebrowserdownloadsanobject,itfirstestablishestheconnectiontobeused(seeFigure1-8).Oncetheconnectionismade,theobjectischeckedtomakesurethatithasnotbeendownloadedpreviously.Ifithasbeendownloadedbefore,itisnotdownloaded,andtheconnectionisclosed.Iftheclasshasnotbeendownloadedbefore,itisdownloaded,andthentheconnectionisclosed. Figure1-8.Downloadperformanceismeasuredbythetimeittakestoperformthestepsinvolved.So,thetimeittakestodownloadanobjectisdeterminedbyfourfactorsasillustratedinFigure1-8:1.Timetoopenaconnection.2.Timetoverifyafile.3.Timetodownloadthefile.4.Timetoclosetheconnection.Andmostimportantly,thesamefourstepsareappliedtoeverysingleclassinyourentireobjectsystem.Nomatterwhatyoudo,youwillhavetospendthetimetodownloadthefiles.There'snogettingaroundthatpartbecauseyouneedthosefilestorunyourapplet.However,thetimespentestablishingandclosingconnectionsisawastebecauseyouareessentiallydoingthesamethingtothesamelocationeachtime.ThebrilliantengineersbehindJavarecognizedthisproblemandcreatedtheJavaArchive.Itenablesyoutogatherallofyourfiles,sticktheminonelargearchivefile,andleteverythinggetdownloadedinonefellswoop.Thismeansthatthereneedonlybeoneopenconnection,onedownload,andoneclosurefortheentiresystemofobjectfiles.UsingJavaArchivesisarathersimpleprocess.Youmustfirstusethejarutility,whichUNIXuserswillfindquitesimilartotheirtarprogram,toarchiveyourfiles.Thisisnotunlike"zipping"abunchoffilesintoone.Oncecompleted,yousimplyspecifythearchiveintheapplettaginyourHTMLcode:...HTMLtexthere...JavaArchivesgreatlyimprovethedownloadperformanceofyourapplets.Withoutsomethinglikethem,appletswouldberestrictedtosmall,compactprogramsthataccomplishlittlemorethananimatingadancingduke.Thetrickisthatthebrowserhastosupportarchives.Currently,NetscapeNavigatorandInternetExplorersupportZIPfiles,andbothplantosupportthejarstandardonceitiscompleted. RuntimePerformanceRuntimeperformanceisadifferentbeastaltogether.Wheredownloadperformancewasarelativelysimpleissuetoresolve,runtimeperformancerequiresasignificantinvestmentincompilertechnology.Thankfully,theJavaengineersareaheadofthecurveonthisaswell.TheyhaveputtogetheraspecificationforaJustInTime(JIT)compiler.RememberthatJavaisaninterpretedlanguage.Thismeansthatthecodeyoudevelopisonlyhalfwaycompiledintobytecodes.Thebytecodesarethentranslatedbyyourlocalvirtualmachineintonativecode.Finally,thatnativecodeisrunonyourmachine.Whenanapplicationexecutes,thebytecodesarewashedthroughthevirtualmachine,andtheresultisthenexecutedonyourplatform.ThisensuresplatformindependencebecausethebytecodesaretranslatedbythevirtualmachineintonativecodeasindicatedbytheflowdiagraminFigure1-9.Figure1-9.PerformanceofJavausingavirtualmachine.Today,non-Javaapplicationsarealwayscompiledforthenativemachine,meaningthatyouarelockedintotheplatformforwhichyouboughtthesoftwarebutcanbypassthevirtualmachinealtogether(seeFigure1-10).Figure1-10.Performanceofnative,non-Javacode.WhenJavacameoutwithitspromiseofplatformindependence,peoplerejoicedbecausetheynolongerhadtodevelopforeverycomputerunderthesun.However,theenthusiasmwastemperedbythefactthatJavawasaninterpretedlanguage,meaningthattheextrastepsinvolvedintranslatingJavacodeintonativecodemade applicationssignificantlyslower.Furthermore,thebytecodesgeneratedbytheJavacompilerwerecreatedwithplatformindependenceinmind.Thismeantthatinordertopreserveanadequatemiddleground,Javabytecodeswerearrangedsothatnoplatformnecessarilygotanadvantagewhenitcametimetotranslateintonativecode.Theendresultwasthatnotonlydidittakeabitmoretimetointerpretthecode,butalsothatthecodewasinterpretedfromaplatform-independentstatecausedtheresultingnativecodetoexecutemoreslowly.TheJITcompilersolvesmostoftheseissuesbyenablingyoutogeneratenativecodefromyourinterpretedbytecode.Thenativecodethenperformsexactlyasitwouldhaveperformedhadtheprogrambeenoriginallyprogrammedinanativelanguage.AsyoucanseefromFigure1-11,theJITexistsaspartofthevirtualmachine,andJITcompilationhappensautomaticallyifthecompilerisinstalled.SomevirtualmachineswillallowyoutoturnoffJITcompilation,butthatshouldbenecessaryinonlyrarecases.Currently,severalvendorsincludingSun,Microsoft,andSymantecareofferingJITcompilersthateithercanbepurchasedasadd-onstoanativevirtualmachineorarebundledaspartoftheirownvirtualmachine.Figure1-11.PerformanceofJavausingaJITcompiler.SummaryofPerformanceIssuesPerformanceisanissueofvitalimportancetoJavaprogrammers.BecauseofJava'spromiseasaplatform-independentlanguage,severalarchitecturaldecisionsweremadetocreatethelanguage.However,someofthesedecisionshavecontributedtoJava'sfaults.Manyoftheseissueshavebeenaddressed,namelydownloadandruntimeperformance.FurtherdeficienciesintheJavalanguagewillbecorrectedastimegoesonifJavaistoachieveitspotential.Ultimately,thegrowthinapplicationsusingthelanguagewilluncoverthesefaultsaswellasthecorrectionstothem.WithseveralofthemajorbenefitsoftheJavalanguageunderourbelt,wecanturntofinallydevelopinganetworkedapplication.Ournetworkedapplicationswillusemanyofthetechniqueswehavediscussedthusfar,aswellasseveralmorewewillintroducealongtheway.Congratulations!YourfirstforayintoJavanetworkingisabouttobegin.AFirstLookatJavaNetworkinginAction SofaryouhavelearnedthethreebasicthingsyouneedtoknowinordertowritenetworkedapplicationsinJava:•Object-orienteddesign•Inputandoutputfundamentals•ThreadingAgoodobject-orienteddesignwillallowyougreatflexibilityincreatingclientsandservers.Youcanextendthefunctionalityofawell-designedclassveryeasily.Youcaneitheralterthenuancesoftheclass'sarchitectureinordertofacilitatethekindofcommunicationyoudesireorpublishyourclasstothe"world"sothatitcanbeusedasitwasintendedtobeused.Solidinputandoutputfundamentalsenableyourclassestoprocessdataquicklyandefficiently.WithastrongI/Ofunctionality,yourclassescanaccept,manipulate,andreturndatawithoutmuchhassle.Andonceagain,youcanpublishyourclasstothe"world,"specifyingexactlywhichdatayouwillacceptandstreamliningtheprocessingpowerofyourobjects.Effectivethreadingprincipleswillenableyourclasstoproducefastturnaroundtimesonobjectrequests(thosemethodsinvokeduponyourobject),makegooduseofsystemresources,andbegintocreateanentirecollectionofobjectsthatworktogetherwithoutaffectingsystemperformance.Figure1-12illustrateshowaservercaneffectivelyhandleinformationbyspawningthreadstoprocessthatinformation.Figure1-12.Threadingcanpreventserversfrombeingboggeddown.Goodnetworkedapplicationshavethreethingsincommon:•Usefulinterfacedefinitions•Pragmaticdatadefinitions•Efficientprocessingofdata Hopefully,thetreatmentofthesethreetopicsinthischaptersofarhasprovidedyouwithameanstosatisfythecriteriasetforthearlierandpublishnetworkedJavaobjectsthattakefulladvantageofthelanguage.PullingItAllTogetherThroughoutthisbook,wewillreimplementthefollowingfeaturedapplication.OurInternetCalendarManagerisasimpletooldesignedtoenableyoutoscheduleappointmentsoveranetwork.BecauseofJava'splatformindependence,youwillbeabletorunthisapplicationonbothyourWindowslaptopaswellasyourSPARCstation.BecausethedataisheldinacentralrepositorywiththeInternetusedasthecommunicationmechanismbetweenthetwo,itwillnotmatterwhereyouruntheapplicationbecause—nomatterwhat—youwillbemanipulatingtheexactsamedata.RoadMapforSuccessYourfirsttaskistooutlineaclearobject-orientedstrategytocompleteyourproject.Forexample,theInternetCalendarManagerwasdesignedwithmodularityasitsmostcrucialelement.Wewantedtobeabletoremoveandreplacecertainpartsoftheprogramasoftenasweneededtowithoutaffectingtherestoftheapplication.Withthatinmind,wecreatedtheclassstructureasshowninFigure1-13.Figure1-13.TheclassstructureofourInternetCalendarManagerwascreatedwithmodularityinmind.Asyoucansee,changingacomponentintheSchedulerdoesnotatallaffecttheCalendarportionoftheapplication.Eachmoduleisentirelyseparatefromtheother.Thisisanexampleofcodereuseandmodularity.Furthermore,theNetworkmodulekeepsournetworkinteractionlimitedtoonemodule.Allinitialization,dataexchange,andremoteinvocationstakeplaceonlyfromwithinthemoduleitself.Furthermore,werecognizedaseriesofobjectsthatwewouldrequirethroughouttheapplication.Mostofthesearenotspecifictotheimplementationofanymodule;rather,theyarehelperobjectsthatdealwithwiderangingthingsfrommultimedia(soundsandpictures)toanimation.TheseobjectswereplacedintheUtilitiesmodulesothattheycouldbeusedasneeded. ProjectPlanningOncetheprojectisdividedaswedidintheprevioussection,wemustdefinetheinterfaceswithwhichobjectswouldtalktooneanother.Inparticular,themodularityoftheNetworkcomponentenabledustoredoitforeachsectionwithoutinanywayaffectingtherestoftheapplication.Infact,theentireNetworkmodulewasn'tevencompleteduntiltwoweeksbeforepresstime.Therestoftheapplicationwasfinishedandworking,talkingtotheNetworkmodule,butwasnevercommunicatingwithanyremoteobjects.UserInterfaceTheInternetCalendarManagerwecreatedisastand-aloneJavaapplication.Wemadeitsoforeaseofuse.AnappletversionofthesameapplicationwillresideontheWebsiteforthisbook.Inanyevent,theUIcomponentsarethesame.Aseriesofbuttonsalongthetopoftheapplicationcontrolwhichofthetwotasksyoucando:addanappointmentordeleteanappointment.PressingtheSchedulerbuttontakesyoutotheAddanAppointmentsection.There,youcanspecifythereasonfortheappointmentandthetimeforwhichyouwouldliketoscheduleit.PressingtheSchedulebuttonsendstheappointmenttotheNetworkmodule,which,inturn,talkstotheserverandplacestheappointmentinthedatarepository.TheCalendarbuttontakesyoutotheCalendarapplication.TheCalendarapplicationallowsyoutoviewalistofalltheappointmentsscheduled,andthereasonsandtimesforthem.Youmayalsodeleteappointmentsfromwithinthisapplication.Thecontentofthecardlayoutisdependentonwhichbuttonyoupress,asshowninFigure1-14.Figure1-14.ThemainGUIforourfeaturedapplication. Finally,theexitbuttongracefullyterminatestheconnection,tellingtheNetworkmodulethatitwantstoexit.NetworkModulesTheNetworkmodulewillbechangedfromchaptertochaptertoreflectthenewformofnetworkcommunication.However,theAPIswillremainthesame.TheNetworkmoduleprovidesanabstractedlayerabovethenetworkcommunicationmechanismofchoice.Insodoing,wecanprovideaseriesoffourmethodsthatareofimportancetotheuser,whilekeepingthenetworkhiddenfromtherestoftheapplication:publicclassNetworkModule{publicvoidscheduleAppointment(Stringreason,inttime);publicVectorgetAppointments();publicvoidinitNetwork();publicvoidshutdownNetwork();} Asfarastherestofthisapplicationisconcerned,theNetworkmodulewillacceptinformationanddosomethingwithitoverthenetwork.Preciselywhatthatsomethingisisofnoconcerntotheapplicationitself.ServersTheNetworkmodulewouldbeuselesswithoutaserverforittotalkto.Everyserverimplementsthesameexactroutines,regardlessofwhetheritisaJavaDatabaseConnectivity(JDBC)server,aRemoteMethodInvocation(RMI)server,oranInterfaceDefinitionLanguage(IDL)server.Infact,theserveritselfisinterchangeable,enablingustochooseontheflytowhichonewewanttotalk.Simplyruntheproperapplicationtotakeadvantageofthecommunicationmechanismofyourchoice.publicinterfaceInternetCalendarServer{voidscheduleAppointment();voidgetAppointments();}Theinterfacedefinitioninthissnippetdoesnottakeintoaccountanykindofdatastructureinwhichtostoreanappointment.Theservercodeimplementsbothoftheforegoingmethods,aswellasestablishesanddefinesthefollowingdatastructure:publicinterfaceInternetCalendarServer{AppointmentType{Stringreason;inttime;}voidscheduleAppointment(AppointmentTypeappointment);AppointmentType[]getAppointments();}Keepinmindthattheinterfacedefinitionsshownarepseudo-codeonly.Aswewillseelater,serverdefinitionvarieswidelybetweeneachcommunicationalternative.InJavaIDLwewillseehowanentirelanguageisavailablewithwhichtodefineservers.InJavaRMIwecancreateserversusingJavaitself.NOTE InanefforttoshowyouhoweasyandfunnetworkprogrammingcanbewithJava,wehavedevisedasimpleapplicationthatwewillredoeverychapter.Inonechapterwewillusesockets,inanotherCORBA.Eventually,youwillhavesixdifferentapplicationsthatdothesamething.Withthesixapplications,youcancompareease-of-useandperformance,aswellasfigureoutwhatallthehubbubisaboutnetworkprogramming.ThenextfourchapterswillexplorethebasicalternativesavailabletonetworkprogrammersintentonusingtheJavalanguage.Chapter2.TCP/IPFundamentals•IntheBeginning…•IPAddresses•ProtocolsIntheBeginning…AttheveryheartofJavanetworking(andmostotherinternetworking)isTCP/IP(TransmissionControlProtocolandInternetProtocol).TCP/IPisaprotocolsuite(i.e.,asetofrulesforexchanginginformation)thatsitsbetweenanapplicationandanetworkthatenablesanapplication(object)ononenodeofanetworktopassinformationbackandforthtoanotherapplication(object)residingonanothernodeofthenetwork.TheapproachusedbyTCP/IPtodothisistoarrangetheprotocolintolayersofsubprotocolsthateachhavetheirownspecificfunction(s)that,whenusedtogether,providearichfunctionalityandanorderlyapproachtodatacommunications.InmanywaysTCP/IPisverysimilartoothersoftware-basedprotocols(i.e.,protocolsthatare"onthewire"protocolslikeEthernet,NETBIOS,NETBUI,SNA).ThemajordifferenceisthewaythatTCP/IPwasdeveloped:Ratherthanbeingaprotocolbasedononemanufacturer'sviewofnetworkinganditsrelationtocorporateprofitability,TCP/IPdevelopedoutoftheideaof"OpenSystems."OpenSystemsaresystemswhosespecificationsaredeveloped"outintheopen"ratherthanbehindcloseddoors;aslongasasoftwaredeveloperimplementsthespecificationfaithfully,thedevelopedsystemisanOpenSystem.TheProtocolStackOneofthethingsthatoftenconfusesprogrammerswhoarenewtotheInternetandTCP/IPistheideaofaTCP/IPstackoraprotocolstack.Theconfusioncomesfromtheterm"stack";programmersautomaticallythinkofastackasinthestackdatastructure.WithrelationtoTCP/IP,thetermstacksimplymeansthatanumberofprotocolsarestackedoneontopoftheotherinamannerthatallowsinformationfromoneleveltobepassedfromonelayertothenextwitheachlayerencapsulatingtheinformationitreceivesfromthepreviouslayer.Movinginformationdownthestackisanalogoustosending,andmovingdataupthestackisanalogoustoreceiving.TheOSIStackIntheearly1980stheInternationalStandardsOrganization(ISO)setoutonapathtodevelopasetofstandardsthatwouldensureinterconnectabilityandinteroperabilityof disparatecomputersystems.ThiseffortstartedandtookplacemainlyinEurope;atthesametime,intheUnitedStates,teamsoftechnologistsfromindustry,government,andtheuniversitieswerebusilyexchangingideasonhowtoarriveatthesamegoalsasISO(i.e.,interconnectabilityandinteroperability).In1983theprotocolsuitethathascometobeknownasTCP/IPwasnamedastheU.S.DepartmentofDefenseStandardandwaseventuallyrequiredonallU.S.governmentcomputersystems.ThroughtheISOwork,theOpenSystemsInterconnection(OSI)referencemodel,referredtoastheOSIstack,showninTable2-1,wasdeveloped.TodaytheOSIprotocolstackremainsprimarilyaEuropeanthing;eventhoughtheTCP/IPprotocolstackisinwiderusethantheOSIstack,theOSIreferencemodel(evenintheUnitedStates)remainstheidealformodelingcommunicationsystems.Table2-2showsacomparisonoftheseven-layerOSIprotocolstackvs.theTCP/IPfour-layerstack.NotethatTCP/IPabstractsthetopthreelayersoftheOSIstack(application,presentation,andsession)intoasingleapplicationlayer.ThebottomtwolayersoftheOSIstack(linkandphysical)areabstractedintoasinglelinklayer.IntheOSImodel,applicationlogicishandledintheapplicationlayer;anythingrelatedtopresentation(dataconversions[ASCII-EBCDIC,ASCII-UNICODE])inthepresentationlayer;andthreading,multiprogramming,andmanagingclientsessionsontheserverinthesessionlayer.InTCP/IPalltheseactivitiesareperformedintheapplicationlayerwithoutrequiringindividualprotocollayersforeachoftheOSIlayers.ThisabstractiononthepartofTCP/IPmakesforlighterweightandmoreagileapplications.TheabstractionofthebottomtwolayersoftheOSImodelisa"makessense"abstractionasthephysicallayerrepresentstheNetworkInterconnectionCard(NIC)andthelinklayeristhedriversoftwarethatcontrolstheNIC.Theselayersareinseparable(i.e.,oneisn'tofmuchusewithouttheother).Table2-1.TheOSIReferenceModelApplicationTELNET,FTP,SMTP,HTTPPresentationByte-order,ASCII-UNICODE,COM-CORBASessionLoginsession,RPCcall,ORB/RMIinvocationTransportEnd-to-endcommunication(withpossibleack)NetworkHost-to-hostcommunication(onehopinapath)LinkNetworkadaptercarddevicedriverPhysicalEthernet,ISDN,PPP,T3,CATVTable2-2.OSIReferenceModelandtheTCP/IPModelOSIModelTCP/IP7ApplicationApplication46Presentation5Session4TransportTransport33NetworkNetwork22LinkLink11PhysicalNotlongago,OSI,TCP,andUDPwerecompetingnetworkstandards;today,TCPcombinedwithUDP-basedIPprettymuchstandsalone(asTCP/IP)astheprimaryInternetprotocol.TheInternetProtocol(IP)codemaintainsroutingtablestomake sureeachIPpacketgetstothenexthopinaroutetowarditsdestination.NotethatoneUDPdatagramoroneTCPsegmentmaybebrokenintomanyIPpackets.EachIPpacketmaytakeadifferentroutefromthesourcetothedestination,andthepacketsmayarriveinadifferentorderthantheyweresent.UDPsendsthereceivedpacketsupwardtowardtheapplicationcodeassoonastheyarrive.TCPcollectstheIPpacketsandassemblesaTCPsegmentbeforesendingitupward,sotheapplicationreceivespiecesofdatainthesameorderitwassent.OneofthemorepronounceddifferencesbetweentheOSImodelandtheTCP/IPmodelisintheareaoferror-handlingphilosophy.TheOSIapproachistorequireerrorcheckingtobedoneforeachhop(nodetonode)apacketmakesthroughthenetwork.Thismeansthatforeachhopapacketwillbeerror-checkedinthenetworklayer(routersusuallyonlyconsistofthelinkandnetworklayers).Ifapacketmakes10hopsingettingfrompointatopointb,theerrorcheckinginvolvedwilloccupyasignificantpercentageoftheoveralltransmissiontime.TheTCP/IPapproachistodoerror-checkingonlyattheendpoints;sincethewholeideaistomovedatareliablyfrompointatopointb,theerror-checkingisdoneonlyoncemakingformuchlessoverheadandfasterend-to-endcommunications.TheTCP/IPStackTheTCP/IPstackconsistsoffourlayers:ApplicationThislayerismadeupofprotocolsdesignedforspecificapplications.ManyTCP/IPprotocolsuitescomewithanumberofclientapplicationsthatimplementsomeofthecommonandwidelyusedprotocolslikeFTP,POP,TELNET.Theseprotocolsconsisttypicallyofasetofcommandstobeissuedbytheclient(instructionstotheservertodosomething)andasetofcommandresponses(thatarepassedbacktotheclient).Informationfromthislayermovesdownthestack.Inthisrespecttheprotocolactuallyfunctionsasaqueue(i.e.,informationmovesdownthestack,fromonelayertothenext,tosendandupthestacktoreceive).Eachprotocollayerwillwrapitsownheaderorheader/trailerinformationaroundwhateveritreceivesfromthepreviouslayer.AttheapplicationlayermostprotocolsareASCIItextbasedandhaveacommandstructuremadeupofkeywordsandstring-basedparametricdata(checkoutthecommand-basedprotocolsforFTPandPOP3).TransportThislayerprovidestheapplicationwithahighlyreliabledatatransmissionmedium(aconnectionismadebetweentwohostcomputersanddatatransfersbetweenthetwoaresized,acknowledgedforreceipt,check-summed,andtimed).NetworkThislayerisprimarilyresponsibleformovingthepacketscreatedinthetransportlayerthroughthenetworkandeventuallytotheirfinaldestination.TheworkhorseofthislayeristheInternetProtocol.LinkThislayerisresponsiblefortranslatingtheIPpacketsreceivedfromIPintotheon-the-wireprotocol(Ethernet,TokenRing,…)andconsistsoftheuser'sNetworkInterconnectionCardandsoftwaredriversrequiredtocontroltheNIC.Note:Someauthorsbreakthelayerintotwolayers—oneforthehardwareinterconnectandoneforthedriversoftware.Thisresembles(atleastconceptually)themodelshowninFigure2-1.Figure2-1.TheTCP/IPprotocolstack. Informationstartingoutinaprogramrunningintheapplicationlayerismoveddownthestacktothetransportlayer.Inthetransportlayertheinformationisbrokenupintoaseriesofsmaller,easier-to-handlechunksfortransmission.EachchunkofdataisencapsulatedwithaTCPheadercontainingsequencinganderror-detectioninformationandmoveddownthestacktothenetwork(IP)layer.Inthenetworklayereachpacketisfurtherencapsulatedbyappendingaheadercontainingnetworkroutinginformationtothebeginningofthepacket.Thenetworklayerinturnpasseseachpackettothelinklayer,whereitisconvertedtotheactual"on-the-wire"protocol(Ethernet,Token-Ring,…)fortransmissionacrossthenetwork.Onitswaytoitsfinaldestination,apacketusuallywillpassthroughoneormorerouters.Routersarefairlyspecializeddevicesanddon'talwaysfunctionwithacompleteTCP/IPstack.Arouteristhenetworkimplementationofamultiplexer;i.e.,oneinputcanbedistributedtoone-of-npossibleoutputs.Todothis,therouterwillhavemultipleNICs.Themainpurposeofarouteristomovepacketsaroundthenetwork;todothis,allitreallyneedstoprovidearethenetworkandlinklayers.AsapacketcomesintotherouteritisreceivedbytheNICandpassedupthestacktothenetworklayer.IPcheckstheroutinginformationandpassesthepacketbackdownthestacktothecorrectNICinthelinklayerandbackoutontothenetwork.UponreachingitsfinaldestinationthepacketisagainreceivedbytheNIC,theNICstripsofftheon-the-wireprotocolinformation(leavinganIPpacket)andpassestheresultinginformationupthestacktothenetworklayer.IPthenremovestheroutinginformation(leavingaTCPpacket)andpassesitupthestacktothetransportlayer.TCPchecksthepacketforerrors,removestheTCPheader,andrebuildstheoriginalapplicationdatabyaccumulatingthepacketsandreassemblingtheoriginaldata(usingthesequencenumbersintheTCPheader).Oncethedatahasbeenreconstructeditispassedbackupthestacktotheapplicationlayer,whereitisactedupon.ThisentireprocessisillustratedinFigure2-2.Figure2-2.Datamovementfromonehosttoanother. NowthatweunderstandthegeneralflowofinformationthroughaTCP/IP-basednetworkletuslookatthestackinalittlemoredetail.We'vealreadysaidthetransportlayerconsistsoftwoprotocols—TCPandUDP—butthesuiteconsistsofmanyotherprotocols.Figure2-3showstheotherprotocolsthatmakeupthesuite(applicationprotocolsareindicatedatthetopofthefigureasplaintextbutareshownonlyasasampleandnotacompleteset).Figure2-3.TheTCP/IPsuite.AlsonotethattherearetwocommonversionsofIP,version4(32-bitaddressing)andversion6(64-bitaddressing)andthatprotocolsthatuseIPalsocomeinbothversion4andversion6flavors.Thisbeingnoted,thefollowingisabriefdescriptionofwhateachoftheprotocolsisusedfor.TCPTransmissionControlProtocol.TCPcanbethoughtofasthepartofthesuitethatmakesIPareliabletool.Itguaranteesthatdatareachesitsintendeddestinationandisreceivedcorrectlyandreceivedinatimelymanner.TCPisrelativelyapplication-orientedinthatusingitssocketfacilitiesprovidesapplicationswithabi-directionalbytestreambetweentwohostslocatedatapplicationendpoints.Aconnection-orientedserviceisbestforapplicationsthatrequirecharacterstobereceivedinthesameorderinwhichtheyweresent,suchaskeystrokestypedfromaterminalorbytesinan ASCIIfiletransfer.Usually,theconnectioniskeptopenforalongtimerelativetothelengthoftimetosetuptheconnection(a"handshake"ofthreeIPpackets).Connection-orientedprotocols,suchasTCP,sendanacknowledgmentwhenthedataisreceived,andtheyretransmitdataautomaticallyifanacknowledgmentisnotreceivedbeforethetime-outperiodhasexpired.Eachacknowledgmentpackettellsthereceivingsidehowmuchbufferspaceisavailableattheotherend.Thisenablesbothendpointstotransmita"window"ofdata,perhapsseveral8Kpackets,beforestoppingtowaitforanacknowledgmentfromtheotherend.Whentheacknowledgmentisreceived,thewindowsizeisupdatedfromthepacketheader.ThisenablesTCPtothrottledatatransferwhenonesideisrunninglowonbufferspaceandtoincreasedatatransferwhentheothersidehasplentyofroomtoreceivedata.UDPUserDatagramProtocol.UDPisconnectionlessandactsmorelikeabroadcastmedium.DatagramssentbyUDParenotguaranteedtoreachtheirdestination.UDPisdesignedforspeed,notreliability.IPInternetProtocol.TheworkhorseoftheTCP/IPsuite,IPtakescareoftheactualmovingofdatagramsfrompointatopointb.ThisisdonebywayofIP'sdatagraminfrastructure.UDPisanapplicationinterfacetoIP.ICMPInternetControlMessageProtocol.ICMPhandlesTCP/IPinternallygeneratederrormessagesandcontrolmessagesbetweenroutersandhostcomputers.Notusedforapplicationlayererrors.IGMPInternetGroupManagementProtocol.IGMPisusedformulticastingandwillnotbediscussedinthistext.ARPAddressResolutionProtocol.ARPmapsIPaddressestohardwareaddresses(everyNIChasamanufacturerprovideduniqueaddress)forbroadcaststylewireprotocols(Ethernet,Token-Ring)butisnotusedbypoint-to-pointwireprotocols(SLIP,PPP).RARPReverseAddressResolutionProtocol.RARPmapshardwareaddressestoIPaddresses.RARPisusedtypicallytoallowtheBootstrapProtocol(BOOTP)toaidadisklessworkstation(X-Station)todiscoveritsIPaddresssothatitsbootimagecanberetrieved.DatagramsNowthatwe'veusedtheterm"datagram"quitefreely,it'sbesttoexplainwhatitis.Basicallyit'stheunitinformationusedintheIPlayer.Tounderstandthisbetter,refertoFigure2-4.Atthephysicallevelofanetwork(whichisn'taddressedbyTCP/IP),thetransmissionmediumisusuallyapieceofwire,fiberopticcable,microwaves,orsomeotherexotictransmissionmedium.Atthislevel,informationtravelsalongasaserialbitstreamwherethebasicunitofinformationisabit.Asthebitsleavethetransmissionmediumandmoveintothelinklayer,theunitofinformationiscalledaframe.Astheframemovesupthestackandthelinklayer'sheaderandtrailerinformationisremoved,theunitofinformationbecomesadatagram.IPremovesitsheaderfromthedatagramandpassestheresulttoTCPasasegment.TCPcollectsthesegmentstogetheruntilithasallthatitisexpectingandpassesitupthestacktotheapplicationasamessage.Thiswholeprocessofreceivingdatacanbethoughtofasacollectingtogetherofallthepieces. Figure2-4.UnitsofinformationfortheTCP/IPstack.IPAddressesNowhereareafewwordsaboutIPaddresses.First,theyarecalledIPaddressesbecausetheyareusedbytheIP(network)layertorouteIPdatagramsaroundtheInternet.Figure2-5showsthefiveclassesofIPaddressesandhowtheyarestructuredfromanumberingstandpoint.ClassesA,B,andCarereservedforprivatenetworksandhavethefollowingaddressspaces:Figure2-5.IPaddressclassesClassA0.0.0.0127.255.255.255ClassB128.0.0.0191.255.255.255ClassC192.0.0.0223.255.255.255ClassD224.0.0.0239.255.255.255ClassE240.0.0.0247.255.255.255ProtocolsWhenaforeigndignitaryarrivesattheWhiteHouse,certainprotocolsareobserved.Thesedescribewhoisintroducedandwhenandwithwhatfanfare.ThePresidentis alwaysintroducedlastandmakeshisorherentrancetothetuneof"HailtotheChief."Aprotocolensuresthatcertainformalitiesareobservedwheninformationisexchangedacrossnetworks.Thisincludestheformatofthemessage,thecontentofthemessage,andthetypeofconnectionusedtosendthemessage.Thereareseveralkindsofprotocols,rangingfromthetime-testedTCP/IPorUDPtothenewerInternetInter-ORBProtocol.Someoftheapplicationlevelprotocolsandapplicationswewillbeexamininginmoredepthinthechaptersthatfollowarementionedhere.DNSSomethingthatwehaven'tdiscussedyetthatisusedineveryInternettransactionistheDomainNameSystem(DNS)anditsprotocol.TheDNSissomethingthatweallbecomeawareofprettyearlyoninouruseoftheInternetbutneverreallyunderstand.IneverthoughtaboutituntilIwasteachinganInternetProgrammingclassonesemesterandwasexplainingtheTCP/IPstackandlayeredprotocols.Oneofthestudentsasked,"HowdoesIPgetthedotteddecimalversionofthedottedwordIPthatwespecifytoourapplications(FTP,TELNET)?"TheDNSisadistributeddatabaseusedfortranslatingdottedwordnotation(http://www.myhome.com)forIPaddressesintothedotteddecimalversion(128.226.183.11).NosingleserverkeepstrackofallIPaddresses;theaddressspaceisdistributedsomewhatregionallyandarrangedinahierarchy.DNSiscommonlyusedasfollows:SupposewewanttoFTPafilefromaremoteserver.OurFTPclientbuildsarequestpacketandsendsitdownthestacktoTCP,whichaddsitsheaderandpushesthesegmentdowntoIP.IPaddsanIPheader,butbeforeitcanitmustresolvetheremotehost'sdottedwordaddresstodotteddecimal.ThisisdonebyIPsendingadatagramrequest(UDPisusedforspeed)tothenearestDNSserver.Ifthatservercan'tresolveit,therequestissentuptheDNShierarchytothenextserver.ThisisdoneuntiltheaddressisresolvedandreturnedtoIPwhereitistranslatedintoa32-bitnumberandaddedtotheIPheader.ManycompaniesanduniversitiesthathavelargeintranetsfortheircampusesruntheirownDNSserversforperformancereasons.Onanintranet,mosthost-to-hostcommunicationsarebetweenhostsonthatsameintranet;theydonotneedtogoouttotheInternettouseaDNSserver.ItmakessensetokeepalocalcopyofthenearestInternetDNSserverlocally.Forprivatenetworks(notconnectedtotheInternet),itmakessensetorunasingleDNSservercontainingonlytheaddressesontheprivatenetwork.HTTPHyperTextTransferProtocol(HTTP)isaTCP/IPapplicationlayerprotocolthatprovidestheconnectivitybetweentheclientandserverforthe"killerapp"ofthecentury.HTTPisbasedrelativelycloselyonanolderprotocolcalledGopher.Gopherprovidedatext-basedclientandserverthatenabledtheretrievalofinformationfromlargecollectionsofresearchdatamaintainedonmainlyuniversitycomputersystems.WhenHyperTextMarkupLanguage(HTML)wasdevelopedfortheMosaicbrowserandtheGopherprotocolwasmodifiedtohandlethetransmissionofgraphics combinedwithtext,thewholefaceofcomputingchanged.ThiscombinationmadetheInterneteasytousefornontechnicalusers.HTTPenabledthedevelopmentoftheWorldWideWeb.Javaisthenextsteptoadvancedistributedcomputinginanobject-orienteddirection.HTTPisdiscussedinChapter7,"WebServers,Server-SideJava,andMore."ItisimportanttorememberthatHTTPisentirelybasedonTCPsockets.CORBAandIIOPTheInternetInter-ORBProtocol(IIOP)isanopenInternetprotocolforcommunicationbetweenobjectsresidingonanetwork.IIOPenablesnetworkobjectstoinvokeoneanotherusinganindustrystandardmessagingsystem(CORBA).WithoutIIOP,objectsontheclientendwouldnotbeabletotalktoobjectsontheserverendwithoutfirstsynchronizingtheirlanguages.IIOPstandardizesthemeansclientsandserversusetoexchangeinformation.Italsoenablesclientsandserversdevelopedusingdifferentapplicationprogramminglanguages(C,C++,Java)tointeractwithoneanother.Aswewillseelaterinthischapter,theformatofthemessagessentbetweenclientsandserversisoftheutmostimportance.Inourdailylives,weevenrequireastandardmessageformat.IfIweretostarttransposingmynounsandverbs(suchas"wereifItransposingtostartmynounsandverbs"),thennoonewouldunderstandme.Similarly,IIOPenablesobjectsimplementedindifferentlanguagestounderstandoneanother.WhenCORBAfirstcameout,itsunderlyingprotocolwasbasedonUDPtooptimizeperformance.AsCORBAhasmatured,IIOPhasswitchedovertoTCPsockets.RMIRemoteMethodInvocation(RMI)isanotherTCPsockets-basedprotocolschemefortheimplementationofnetworkobjects.ThegeneralideaofRMIisthateverynetworkobjectconsistsofaclientpieceandaserverpiece.Wouldn'titbeniceifthisobjectcouldbetreated(fromanapplication'sstandpoint)justlikeanylocalobject.RMIprovidesaninfrastructurethatdoesjustthat.ThemaincomplaintaboutRMIcomesfromthefactthattheprotocolisnotopenlydevelopedorpublished.Becauseofthecomplaintsoverthis,SunMicrosystemshasagreedtobaseclient/servercommunicationsonIIOPinsomefuturereleaseofRMI.ThecurrentimplementationusesJavaserializationAPIsandTCPsocketstoprovidetheunderlyingcommunicationsinfrastructure.JINIJINI,ratherthanbeingstrictlyaprotocol,isatechnologynotforclient/serverapplicationsbutfortheinterconnectionofJINI-enableddevicesintoimpromptunetworks.AnexampleofthiswouldbethatIgooutandbuyanXYZJINI-enabledcolorprinter.WhenItakeithomeandplugitintomywholehouseEthernet,theprinterautomaticallyregistersitselfanditsdriverswiththenetwork.IturnonmyJINI-enabledworkstationandgetintomyfavoritewordprocessorandasktoprintincolor(atthispointmyworkstationonlyknowsaboutmyblackandwhiteprinter).Theprintfunctioncallsouttothenetwork"isthereacolorprinteroutthere?"Thenetworkrespondsandtransparentlydownloadsthedriverforthecolorprintersothatthewordprocessorcansenddatatotheprinter.Justthink,Ididn'thavetoinstallthedrivers(or evenfindthem);theprinterhaditsowndriversbuiltinandmadethemavailabletothenetwork.Chapter3.JavaSocketsandURLs•SocketsandInterprocessCommunication•Client/ServerMethodology•ThePizzaOrderProtocol(TPOP)•TheTPOPServer•TheTPOPClientSocketsandInterprocessCommunicationAttheheartofeverythingwediscussinthisbookisthenotionofinterprocesscommunication(IPC).Inthischapter,wewilllookatsomeexamplesusingJavamechanismsforinterprocesscommunication.IPCisafancywayofsaying"twoormoreJavaprogramstalkingwitheachother."Usuallytheprogramsexecuteondifferentcomputers,butsometimestheymayexecuteonthesamehost.IntroductiontoIPCWhenyoucallCharlesSchwabtocheckonyourstockportfolio,youdialatelephonenumber.Onceconnected,youpresssometelephonebuttonstorequestvariousservicesandpressotherbuttonstosendparameters,suchasthenumericcodesforstocksymbolsinwhichyouareinterested.Youmaythinkofyouraccountasanobjectwithdifferentmethodsthatyoucaninvoketopurchaseortosellstocks,togetcurrentquotes,togetyourcurrentpositioninastock,ortorequestawiretransfertoaSwissbank.Youareaclientandtheotherendisaserver,providingtheservices(methods)yourequest.Ofcourse,theserveralsoprovidesservicestomanyotherclients.Youcanbeaclientofotherservers,suchaswhenyouorderapizzawithapushbuttontelephone.Sometimesaservercanbeaclientaswell.Amedicalrecordsqueryservermayhavetosendarequesttotwoorthreehospitalstogathertheinformationyourequestforapatient.Thusyourserverbecomesaclientofthehospitalserversitqueriesonyourbehalf.Allthesesituationsareexamplesofinterprocesscommunication.Eachclientandeachserverresideindifferentprocesses.Sometimesyou,theindividual,aretheclient;othertimesitisacomputer.Sometimestheserverisanapplicationthatlistensinonwhatyoutypeonyourtelephonepadandprocessestheinformation;othertimesitwillbeaprogram,perhapswritteninJavaaswewilldolaterinthischapter.IPCishowourapplicationscommunicate,butitalsoreferstothemechanismweuse.ThischapterexploresthefundamentalsofIPCusingsomethingcalledasocket.Sockets Thecommunicationconstructunderneathallthiscommunicationismorethanlikelyasocket.Eachprogramreadsfromandwritestoasocketinmuchthesamewaythatyouopen,read,writeto,andcloseafile.Essentially,therearetwotypesofsockets:•Oneisanalogoustoatelephone(aconnection-orientedservice,e.g.,TransmissionControlProtocol)•Oneisanalogoustoamailbox(aconnectionless"datagram"service,e.g.,UserDatagramProtocol)AnimportantdifferencebetweenTCPconnectionsocketsandUDPdatagramsocketsisthatTCPmakessurethateverythingyousendgetstotheintendeddestination;UDP,ontheotherhand,doesnot.Muchlikemailingaletter,itisuptoyou,thesender,tocheckthattherecipientreceivedit.Thedifferencebetweenthetwoprotocolsisverysimilartocomparingthedifferencesbetweenusingthephonetotalktofriendsandwritingthemletters.Whenwecallafriendusingatelephone,weknowatalltimesthestatusofthecommunication.Ifthephoneringsbusy,weknowthatwehavetotrylater;ifsomeoneanswersthephone,wehavemadeaconnectionandareinitiatingthemessagetransfer;ifthepersonthatansweredthephoneistherightperson,wetalktothemtherebytransferringwhateverinformationweintendedtodeliver.Hadwewrittenaletter,weknowthatwewouldhaveinitiatedaninformationtransferafterwedroppeditoffatthemailbox.Thisiswhereourknowledgeofthetransfer,inmostcases,ends.Ifwegetaletterbackanditstartsoutwith"Thanksforyourletter,"weknowthatourletterwasreceived.Ifweneveragainhearfromtheperson,thereissomedoubtthattheyeverreceivedourletter.Sometimeswhenyouusethepostalservice,yourletterbecomes"lostinthemail."Whentheletterabsolutely,positivelyhastobethere,youmayneedamorereliableformofpostage.Similarly,yourchoicebetweenusingadatagramoraconnectionsocketiseasilydeterminedbythenatureofyourapplication.Ifallyourdatafitsinan8Kdatagramandyoudonotneedtoknowifitwasreceivedattheotherend,thenaUDPdatagramisfine.MailingpartyinvitationsisoneexamplewhereUDPismoreappropriatethanTCP.Ifthelengthofservicewarrantstheexpenseofestablishingaconnection(threehandshakepackets),oritisnecessarythatallthepacketsbereceivedinthesameorderastheyweresent,suchastransferringafilethatismorethan8Kbyteslong,thenaTCPsocketmustbeused.Likewise,ifweweretomailourimportantpackageusingsomethinglikeFederalExpress,wewouldbeabletotrackthepackageandknowwhenitarrivesatitsdestination.Hereisanotherwaytolookatthis.Supposewehaveaserverthatissomewhereonthenetworkbutwedon'tknowwhere.Tocommunicatewiththistypeofserver,wemustfirstannounceourpresence,listenforananswer,andthencarryontheconversationinlockstepwherefirstoneendsendsthenlistenswhiletheotherendlistensthentalks.Thisislikeastudentwalkingintothereserveroomofacollegelibraryand,uponnotseeingthelibrarianrightaway,saying,"Isthereanyonehere?"andthenlisteningforaresponse."Goodafternoon,I'llbewithyouinamoment." "I'dlikethebookProf.SteflikputonreserveforCS-341.""Hereitis.PleaseleaveyourStudentIDcard."Weannouncedourpresenceandstartedlistening.Theserverwaslistening,heardus,repliedwithanimpliedgoahead,andreturnedtolistening.Weheardtheserver'sresponse,announcedwhatwewanted,andreturnedtolistening.Theserver(librarian)heardourrequest,retrievedtheinformation(thebook),anddeliveredit.Thisbackandforthtypeofcommunicationisknownashalfduplex,whereonlyoneendpointtalksatatime;contrastthiswithfullduplex,wherebothendpointscantalkandlistenatthesametime.NOTEAsocketissometimescalleda"pipe"becausetherearetwoends(orpointsasweoccasionallyrefertothem)tothecommunication.Messagescanbesentfromeitherend.Thedifference,aswewillsoonsee,betweenaclientandaserversocketisthatclientsocketsmustknowbeforehandthatinformationiscoming,whereasserversocketscansimplywaitforinformationtocometothem.It'ssortoflikethedifferencebetweenbeingrecruitedforajobandactivelyseekingone.Inthischapter,wewillwriteanonlineorderingapplication,usingTCP,andabroadcastcommunicationapplication,usingUDP.Theseapplicationswillusethefollowingclassesfromthejava.netpackage,asillustratedinTable3-1.Table3-1.Java.net.*TypesandTheirCorrespondingProtocolMechanismDescriptionSocketTCPendpoint(a"telephone")ServerSocketTCPendpoint(a"receptionist")DatagramSocketUDPendpoint(a"mailbox")DatagramPacketUDPpacket(a"letter")URLUniformResourceLocator(an"address")AnactiveconnectiontoanInternetobject(e.g.,aCGI-binscript,aDayTimeURLConnectionservice)WhatAreSockets?AttherootofallTCPandUDPcommunicationsisavirtualdevicecalledasocketoraport;thetermsareprettymuchinterchangeable.SocketsareavisualizationmechanismforasoftwarebufferingschemethatisimplementeddeepinthebowelsofthetransportlayeroftheTCP/IPstack.Theterm"socket"actuallycomesfromtheold-fashionedtelephoneswitchboardthatLilyTomlin'scharacterErnestine,thetelephoneoperator,uses.Theconceptisprettysimilar:Eachsocketintheswitchboardrepresentsapersonorservicethatanincomingcallcanberoutedto;whenanincomingcallisanswered,theoperatorconnectsittotheappropriatesocket,therebycompletingtheconnectionbetweentheclient(thecaller)andtheserver(personbeingcalled).Inthetelephoneswitchboardeachsocketrepresentedaspecificpersonorservice;inTCP/IPcertainsocketsarededicatedtospecificagreed-uponservices. Ifweweretolookatthepacketlevel,wewouldseethatasocketisreallyidentifiedbya16-bitnumbertherebygivingusabout65,000possiblesockets.Thefirst1024socketsarededicatedtospecificagreed-uponservicesandarethereforecalledwell-knownports.Foreachoftheservicesprovidedonthewell-knownports,thereisacorrespondingprotocolthatdefinesthemannerinwhichclientsandserversusingthatportshouldcommunicate.TheprotocolsthemselvesarearrivedatthroughaprocessknownastheRFCprocess.Table3-2listssomeofthemorecommonTCP/IPservices,their"well-known"ports,andtheirrespectiveRFCs.EveryInternetstandardstartsoutasa"RequestforComment"orRFC.ThroughaninteractiveprocessanRFC,if"worthy,"willberefinedanddevelopedbytheInternetcommunityintoastandard.ExploringSomeoftheStandardProtocolsWhenstartingtounderstandsocketsprogramming,it'salwaysbesttostartoutbyexaminingthe"trivial"protocolsfirstandthenmoveontothemorecomplexandfinallytoourown,application-specificprotocols.ThetrivialprotocolsareasubsetofInternetprotocolsthataresimple,straightforward,andeasytoimplement.Table3-2.SomeWell-KnownPortServicesPortProtocolRFC13DayTimeRFC8677EchoRFC86225SMTP(e-mail)RFC821(SMTP)RFC1869(ExtndSMTP)RFC822(MailFormat)RFC1521(MIME)110PostOfficeProtocolRFC172520FileTransferProtocol(data)RFC95980HypertextTransferProtocolRFC2616DaytimeTheDaytimeserviceisusuallyprovidedonTCPandUDPport13.AssumingthatwehavetheaddressofahostthatisrunningtheDaytimeservice,theoperationisstraightforward.UsingTCPtheclientconnectstotheDaytimeport(13)ontheremotehost;theremotehostacceptstheconnection,returnsitscurrentdateandtime,andclosestheconnection.ThiscanbeeasilydemonstratedusingtheWindows95Telnetclient.OpenuptheTelnetclientandclickonConnectandtheRemoteSystem.EnterintheaddressofyourhostthatprovidestheDaytimeservice,selecttheDaytimeport,andclickConnect.Noticethatadate/timestampisdisplayedintheclientareaandthatasmalldialogboxindicatesthattheconnectiontothehosthasbeenlost.Thisexampleistrivialbutillustratestwothings:First,theWindowsTelnetclientcanbeusedtoexplorestandardTCP-basedprotocols(we'llseethislaterwithotherprotocols.Second,wereallydiddemonstratehowtheclientendoftheprotocolworks;theclientmakesaconnectiontotheserver,theserversendsthetimestampandclosestheconnection,and,finally,theclientreceivesthetime-stamp.Toimplementourownclient,understandingwhattheclientneedstodomakesthetaskquitesimple.Ahigh-leveldesignis CreateasocketCreateaninputstreamandtieittothesocketReadthedatafromtheinputstreamanddisplaythereultTocreateasocket,defineavariableforthesocketclassandinitializeitusingtheclassconstructor:Sockets=Socket("localhost",7);"localhost"isthenameassignedtoaddress127.0.0.1inyourhostsfile;address127.0.0.1isknowntraditionallyasyourmachine's"loopbackport,"andletsyourmachinetalktoitself.Thelineabovecreatesasocketnamed"s"andconnectsittoport7onyourloopbackport.ToconnecttotheDaytimeserviceonanyotherhost,justreplacelocalhostwithastringcontainingthedotteddecimalnameorIPaddressofwhateverhostyouwanttoconnectto.Thissingleinstructionwillcreatethesocketobjectandattempttoconnectittothespecifiedhost.Becausethishasapossibilityoffailing(throwinganexception—aconnectionmaynotbeestablished),weneedtocodeitinatry/catchconstruct.importjava.io.*;importjava.net.*;publicclassDayTimeClient{publicstaticfinalport=13;publicstaticvoidmain(Stringargs[]){Sockets=null;Stringtimestamp;try{//createthesockettotheremotehosts=newSocket(args[0],port);//createaninputstreamandtieittothesocketInputStreamin=s.getInputStream();BufferedReaderin=newBufferedReader(newInputStreamReader(in));//tellusertheyareconnectedSystem.out.println("Connectedto:"+s.getInetAddress()+"onport"+s.getPort());while(true){//readthetimestamptimestamp=in.readLine();if(timestamp==null){System.out.println("Serverclosedconnection");break;}System.out.println("Daytime:"+timestamp);}}catch(IOExceptione){System.out.println(e);} finally{//forcetheconnectionclosedincaseit'sopentry{if(s!=null)s.close();}catch(IOExceptione2){}}}}Thecodefollowsourhigh-leveldesignprettyclosely.Wefirstcreateasocketandthencreateastreamandtiethetwotogether.NoticethatallI/OisdoneinatryconstructsothatallI/Oproblems(socketorstream)areautomaticallycaughtasexceptions.Infact,especiallynoticethatthefinallyclauseofthemaintry/catch/finallyusesanestedtrytocatchthefactthatiftheconnectionisalreadyclosedsothatwecanterminatetheprogramgracefullyinthenullcatchstatement.Nowthatwe'vemasteredthemosttrivialoftheprotocols,let'smoveontosomethingalittlemorecomplicated.Echo"Well-knownport"7onmosthostsprovidesaservicecalledecho.Echoisprettymuchadiagnosticserviceandworksasfollows(seeRFC862onthecompanionCDROMforafullerdescription):1.Theclientconnectstotheserveronport7andproceedstosenddata.2.Theserverreturnseverythingitreceivestotheclient.Thismaybedoneonacharacter-by-characterbasisoraline-by-linebasisdependingontheimplementationoftheserver.Let'sstartoutourexaminationofechobyfirstwritinganon-sockets-basedversionofEchojusttogetafeelforwhatitisthatwewanttodo.publicclassEchoTest{publicstaticvoidmain(Stringargs[]){BufferedReaderin=newBufferedReaderNewInputStreamReader(System.in));Stringline;while(true){line="";try{line=in.readLine();}catch(IOExceptione){System.err.println(e.getMessage());} System.out.println(line);}}}Theprogramisquitesimpleandstraightforward.First,wedefineaninputstreamandconnectittothestandardinputkeyboard(System.in);thenwedefineastringforouronlyprogramvariable,whichwillholdthestringwereadfromthekeyboardandprintontheJavaconsole.Finally,weputthereadandwriteinadoforeverloop.Remember,inJavaitisnotonlyconsideredgoodformtoprovidetry/catchconstructswhendoingI/Oitisnecessaary.Youcanexecutetheprogramthatwecreatedbydoingthefollowing,andgetsimilarresults:%prompt%javacEchoTest.java%prompt%javaEchoTestabcinput…abc…outputdefinput…def…outputxyzinput…xyz…output^C%prompt%MovingEchoTesttoSocketsTakinganothersteptowardproficiencyusingJavasockets,wemodifyourechoprogramtodothefollowing:1.Readalinefromthekeyboard.2.WriteittoasocketconnectedtoTCPport7.3.Readthereplyfromthesocketconnection.4.Printthelinefromthesockettothescreen.Asocketobjectiscreatedasfollows:Sockets=Socket("localhost",7);ThetwoargumentstotheSocketconstructorarehostnameandportnumber.Weuse"localhost"tokeepitsimple.ThehostnameispassedasaStringvariable,typicallyfromthecommandlineandtheportnumberasanint.HereisasimpleTCPclientwritteninJava.First,wemustcreatetheEchoClientclassandimportalltheJavalibrariesthatwewilluseinourprogram. importjava.io.*;importjava.net.*;publicclassEchoClient{}Now,wemustcreateafunctioninwhichwewillplacealoopsimilartotheonewecreatedwithourJava-onlyclient.Thisloopmusthavetwoobjectsonwhichtoact—theBufferedReaderfromthesocketfromwhichitwillgetdataandthePrintStreamfromthesockettowhichitwillwritedata.WeassumedthiswasstandardinputandstandardoutputforourJava-onlyclient,butwewillnotmakethatassumptionhere:importjava.io.*;importjava.net.*;publicclassEchoClient{publicstaticvoidechoclient(BufferedReaderin;PrintStreamout)throwsIOException{}}Now,wemustgetaninputstreamforthekeyboard.Forthiswe'lluseanotherBufferedReadertiedtoSystem.in.Wewillalsoaddtheloophere.Theloopwillfirstgetinputfromthekeyboardusingthestreamwejustcreated.Thenitwillwritethatdatadirectlytothesocket.importjava.io.*;importjava.net.*;publicclassEchoClient{publicstaticvoidechoclient(BufferedReaderin;PrintStreamout)throwsIOException{kybd=newBufferedReader(newInputStreamReader(System.in);Stringline;while(true){line="";//readkeyboardandwritetothesockettry{line=kybd.readLine();out.println(line); }catch(IOExceptione){System.err.println(e.getMessage());}}}}Tofinishup,wenowreadtheactivityonthesocketandstickitonthescreenbywritingtotheJavaconsoleusingtheSystemobject.publicclassEchoClient{publicstaticvoidechoclient(BufferedReaderin,PrintStreamout)ThrowsIOException{//makeastreamforthekeyboardBufferedReaderkybd=newBufferedReader(newInputStreamReader(System.in));Stringline;//forreadingintowhile(true){line="";//readkeyboardandwritetoTCPsockettry{line=kybd.readLine();out.println(line);}catch(IOExceptione){System.err.println(e.getMessage());}//readTCPsocketandwritetojavaconsoletry{line=sin.readLine();System.out.println(line);}catch(IOExceptione){System.err.println(e.getMessage());}}}}Finally,wecancreateourmainapplication.Inourmainapplication,wewillcreatethesocketfirstandthengetaBufferedReaderandaPrintStreambasedonit.This enablesustoreadandwritetothesocketeasily,aswellaspassitontothefunctionwecreatedearlier.Oncewearefinished,wemustclosetheconnectiontothesocket.CAUTIONAswewilldiscusslater,toomanyopenconnectionsareasystemliability.Ifaconnectionisnotinuse,butisstillopen,otherapplicationsmaynotbeabletoconnecttotheporttowhichyouareconnected.importjava.io.*;importjava.net.*;publicclassEchoClient{publicstaticvoidechoclient(BufferedReaderin,PrintStreamout)throwsIOException{//makeastreamforreadingthekeyboardBufferedReaderkybd=newBufferedReader(newInputStreamReader(System.in));Stringline;while(true){line="";//readkeyboardandwritetoTCPsockettry{line=kybd.readLine();out.println(line);}catch(IOExceptione){System.err.println(e.getMessage());}//readTCPsocketandwritetoconsoletry{line=in.readLine();System.out.println(line);}catch(IOExceptione){System.err.println(e.getMessage());}}}publicstaticvoidmain(String[]args){Sockets=null;try{//Createasockettocommunicatewith"echo"//onthespecifiedhosts=newSocket(args[0],7); //Createstreamsforreadingandwriting//linesoftextfromandtothissocket.BufferedReaderin=newBufferedReader(newInputStreamReader(s.getInputStream()));PrintStreamout=new(PrintStream(s.getOutputStream());//Telltheuserthatwe'veconnectedSystem.out.println("Connectedto"+s.getInetAddress()+":"+s.getPort());echoclient(in,out);}catch(IOExceptione){System.err.println(e);}//Alwaysbesurethesocketgetsclosedfinally{try{if(s!=null)s.close();}catch(IOExceptionexc){;/*terminategracefully*/}}}}Whenweexecuteourprogram,wesendamessagetotheEchosocket,readwhateverinformationcomesbackonthesocket,andthenprintit.Becausetheechosocketmerelytakeswhateverinputitgetsandbouncesitrightbacktotheport,whatwegetinreturnonthesocketisexactlywhatwesent.Theoutputisdisplayednext.Ifyouneedtoconnecttoanotherhost,substituteitsnameforlocalhost.%prompt%javaEchoClientlocalhostConnectedtolocalhost/127.0.0.1:7abcrequest…abc…replyxyzrequest…xyz…reply^CThisservice(andmostothers)canbetestedusingtheTelnetclientthatisavailableasanapplicationwithmostTCP/IPstacks.Inthiscase,theTelnetprogramactsinthesamemannerasourclient,sendinginformationtotheportandreadingwhateveritgetsback.%prompt%telnetlocalhost7Trying127.0.0.1…Connectedtolocalhost. Escapecharacteris'^]'.abcrequest…abc…reply^Cxyzrequest…xyz…reply^]control-right-brackettelnet>quitConnectionclosed.URLandURLConnectionBeforeweleavethetopicofusingsocketstoconnectexistingInternetservers,let'slookatusingsomeofthemorecommonandpopularservicesprovidedontheInternet.Weneedtoexamineacoupleofothermembersofjava.net:URLandURLConnection.AUniformResourceLocator(URL)isastringthatidentifiesaresourceontheInternet.RFC1738givesanin-depthdescriptionofeverythingyouwouldeverwanttoknowaboutURLs.Table3-3isabriefdescriptionofthevariousthingsthatmakeupaURL.Table3-3.MakeupofaURLProtocolAnidentifier(usuallyanacronym)thatspecifiestheprotocoltousetoaccesstheresourceHostnameThenameofthehostordomainwheretheresourceislocated(www.binghamton.edu,localhost)PortTheTCP/IPportnumberthattheserviceisbeingprovidedonnumberFilenamePath-andfilenameofresourceReference#anchornameTheURLclassgivesustheabilitytoconstructURLobjectsandanumberof"getter"methodsthatletusextractthevariouspartsofaURL.Fromanetworkingstandpoint,themethodsofgetContent(),openConnection(),andopenStream()provideuswithsomeveryusefultoolsthatwecanusetointerfacewithanumberofprotocolservers.ToretrieveafilefromaWebserver,allwereallyneedtoknowisitsURL:ClassGetURL{try{Stringhost="watson2.cs.binghamton.edu";Stringfile="~steflik/index.html";Stringline;BufferedReaderin;URLu=newURL("http://"+host+"/"+file);Objectcontent=u.getContent();System.out.println("class:"+content.getClass());System.out.println("content:"+content.toString());In=newBufferedReader (newInputStreamReader(u.openStream()));while((line=in.readLine()!=null){System.out.println(line);}}catch(MalformedURLExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}}AllwehadtodowascreateaURLobjectandthenusetheopenStream()methodtocreateanInputStreamandeventuallyaBufferedReaderthatwecanusetoretrievethefile.Atthispointallthatisneededisalooptoreadthelinesoutofthefile.Thistechniquecanbeexploitedfordoingthingslikepopulatingselectionlistsinanapplet-basedshoppingcartapplicationwithdatafromasetofpricingfileskeptontheWebserver.ThistechniquecanalsobeusedtorunscriptsstoredonaWebserver.SummaryofSocketsWehaveshownyouwhat,inthemostbasicsense,socketsareandhowtheyareusedinJavatobuildclientapplicationsthatcommunicate,usingwell-definedprotocolswithstandards-based(developedusingtheRFCprocess)servers.Thesubsequentsectionsinthischapterbuildonthismaterialandshowyouhowtocreateanentireclient/serversystemusingonlysockets.TherestofthisbookshowcasesseveralotherJavacommunicationtechnologiesthatusesocketsastheirunderlyingmechanismtotransferdataacrossnetworks.Inthelargeofit,applicationsuseprotocolstodirectthewaytheytalktooneanotherandprotocolsusesocketsastheirnetworkinterface.Client/ServerMethodologyIntheprevioussectionwedevelopedclientapplicationsforserversthatalreadyexist.Thisisn'tthewaythatwewouldnecessarilyapproachdevelopingasockets-basedclient/serverapplication.Inthenextfewpageswewillexamineaclient/serverapplicationforanInternet-basedpizzaordering/deliveryservicethatwillbemadeupofaclient(thatpizzaloversaroundthecommunitycaninstallonthehomecomputerstoorderapizza),aserver(runningatthestore),andaprotocolthatdirectstheinformationexchangebetweentheclientandtheserver.SupposethatyouareathomewithyourcronieswatchingtheSuperBowl,and,asluckwouldhaveit,theWashingtonRedskinsareplaying.Asinvariablyhappens,you'verunoutofnachosanddipbeforehalftime,soyoudecidetoreplenishthenutritionsupplybyorderingapizza.Today,whenyouwanttoorderthatpizza,youpickupthephoneandcallyourfavoritepizzariatorequestadelivery.Afewyearsago,asmallstart-upcompanyintheSiliconValleycalledtheSantaCruzOperation(SCO)developedanInternetpizza-orderingapplication.Bytoday'sstandards,itwasquitelow-tech,basedsolelyonHTMLformsandrequiringsomeonetoreadtheinformationmanuallyontheotherendviae-mail.TheniftythingaboutthisInternetPizzaHutwastheideathatyoucouldsimplyuseyourcomputerto communicatewithafarawayplaceandgetapizza.Inthissense,SCOwasprettywellaheadofthegame—theywereamongthefirsttogenuinelyusetheInternet,notthecorporateintranet,toconductbusinesswithremoteusers.Inthissection,wewilldevelopourownpizzaclient/serversystemasanultra-hiphigh-techalternativetothetelephoneandpublishittotheworld.Thistime,however,wewilluseJavaandimplementourPizzaServerusingsockets.ThePizzaOrderProtocol(TPOP)Todesigntheprotocolweneedtoexaminewhatinformationmustbepassedfromtheclienttotheserverandviceversa.IftheuserinterfaceforourclientapplicationisasshowninFigure3-1wecanreadilyseethattoconstituteanorderweneedtosendthename,address,phonenumber,pizzasize(small,medium,orlarge),andwhichtopping(Veggies,Meat,orCalifornia)istobeaddedtoastandardcheesepizza.Figure3-1.AsampleGUIforthePizzaTool.Theprotocolthatisrequiredtoplaceanorderisprettysimple,asshowninTable3-4.Letusfurtherdecidethat,sincewe'reinthisearlypartofdesign,alldataexchangedbetweentheclientandtheserveristobeasplainoldtextstrings(inthetruetraditionoftheInternet),eachofwhichistobedelimitedbythe"|"character. Thenextdecisionweneedtomakeiswhichcomponentwewilldevelopfirst:theclientortheserver.Ifwechoosetodeveloptheclientfirst,wewon'tbeabletotestituntilwedeveloptheserverandthenendupwiththepossibilityofhavingtousetwountestedpiecesofsoftwaretotesteachother.Realizingthepossibledisasterthatcanoccurifthisavenueisfollowed,let'sthinkaboutdevelopingtheserverfirst.Iftheserverisrunning,wecanalwaystestitusingourTelnetclient.Todothis,allwedoisstartupourTelnetclient,connecttoport8205oftheserver,typeinthedataseparatedby"|"characters,andpressEnter.Theserverwillprocessthedata,sendbackthepriceinformation,and,closetheconnection.Thisapproachhelpssetusupforsuccessratherthanfailure.Table3-4.TPOPClientServerStartserverlisteningonport8205Connecttoport8205oftheserverAccepttheconnectionandspawnathreadtohandletheconnectiondataSendtheorderinformationandthenwaitforthepricetodisplayReceivetheorder,printitout,calculatetheprice,returnpricetoclientapplication,andbreaktheconnectionDisplaythepriceTheTPOPServerServerMethodologyForeveryclienttheremustsomewherebeaserver.Inanattempttomakeservercreationassimpleaspossible,JavaprovidesaServerSocketclassaspartofjava.net.ServerSockets,oncecreated,listenontheirassignedportforclientconnectionrequests.Asrequestsarereceived,theyarequeuedupintheServerSocket.TheServerSocketacceptstheconnectionrequest;aspartofthisacceptancetheServerSocketcreatesanewsocket,connectsittotheclient,anddisconnectstheconnectionontheServerSocketport,leavingitopenformoreconnectionrequests.Theclientandservernowtalkbackandforthonthenewsocketconnection,andtheserverlistensforconnectionrequestsontheServerSocket.Thisallsoundsprettysimple,butwehaven'tmentionedanythingaboutthreadsyet.Oneofthebasicideasofclient/servermethodologyisthatoneservershouldserviceasmanyclientsaspossible.Todothistheremustbesomethingintherecipethatprovidesparallelism.Thatsomethingisthreads.TheThreadclassprovidesJavawithaconsistent,operatingsystemneutralwayofusingthethreadingcapabilitiesofthehostoperatingsystem.Javathreads,sockets,andAWTcomponentsaresimilarinthattheclassesprovidedarereallyinterfacestothethreads,sockets,andGUIwidgetssuppliedbytheoperatingsystemthatishostingtheJavavirtualmachine.ThismeansthatifyouareonWindows,youarereallyinteractingwiththeTCP/IPprotocolstackprovidedbywinsock.dll;ifyouareonaUNIXplatform,youaremostlikelyusingBerkleysockets.IfyouareonaSun Solaris,youareusingthethreadingprovidedbytheSolarisoperatingsystem.IfyouareonWindows98usingAWTwidgets,youarereallyusingthewidgetsprovidedbyWindows.UsedthiswaybyJava,thesecomponentsareknownaspeercomponentsorobjects.TheaddingoftheSwingcomponentstoJava1.1startstogetawayfromthisbyproviding100%JavaGUIcomponents.AtypicalTCPapplicationopensa"well-known"porttoreceiveconnectionrequests,andthenitspawnsachildprocessoraseparatethreadofexecutiontoperformtherequestedservice.Thisensuresthattheserverisalwaysreadyformoreinvocations.Asingle-threadedservermustpollthesocketsconstantly.Whenitdetectsactivity,itmustspawnanewprocesstohandletheincomingrequest.Ourmultithreadedservercansimplywaitforinformationonasocketandspawnathreadtohandleincomingrequests.ThePizzaServerthatwewillimplementwillhangonport8205andwaitforinformation.Whentheclientsendsitsbar-delimitedrequest,theserverwillspawnathreadtohandletherequest.Thethreadreadstheinformation,processesit,andsendsareply.SettingUptheServerWemustcreatethePizzaServerobjectitself.ThePizzaServerisastand-aloneJavaapplicationwithitsownapplicationmain(ontheaccompanyingCD,twoversionsoftheserverareprovided—onewithaGUIinterfaceandonewithout).WemustalsocreateaPizzaThreadthatinheritsfromtheJavaThreadclass.Thisthreadedobjectwillbecreatedeverytimewedetectactivityontheport.AswediscussedinourChapter1sectiononthreads,itisoneoftwowayswecouldhaveimplementedtheserverobject.Weleavetheotherthreadedversionasanexercisetothereader.importjava.net.*;importjava.io.*;importjava.lang.*;importjava.util.*;publicclassPizzaServer{publicstaticvoidmain(Stringargs[]){}//threadedpizza!classPizzaThreadextendsThread{}InitializingtheServerSocket Insidethemainprogram,wemustcreateaServerSocket.TheServerSocketisaJavatypewhosesolepurposeistoenableyoutowaitonasocketforactivity.Initializeitbyspecifyingtheportonwhichyouwanttowait.importjava.net.*;importjava.io.*;importjava.lang.*;importjava.util.*;publicclassPizzaServer{publicstaticvoidmain(Stringargs[]){//initializethenetworkconnectiontry{ServerSocketserverSocket=newServerSocket(8205);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}//threadedpizza!classPizzaThreadextendsThread{}CreatingtheThreadThePizzaThreadobjectwillacceptonevariable,theincomingsocketfromwhichitgathersinformation.Weneedtospecifythisherebecausethemainserverprogramhasalreadygrabbedholdofthesocket,andwedon'twanttodosotwice.Wemerelypassthesocketobtainedbythemainprogramontothethread.Wewillalsoimplementtherunmethodforthethread.importjava.net.*;importjava.io.*;importjava.lang.*;importjava.util.*;publicclassPizzaServer{publicstaticvoidmain(Stringargs[]){//initializethenetworkconnectiontry{ServerSocketserverSocket=newServerSocket(8205);} catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}//threadedpizza!classPizzaThreadextendsThread{//thesocketwearewritingtoSocketincoming;PizzaThread(Socketincoming){this.incoming=incoming;}//runmethodimplementedbyThreadclasspublicvoidrun(){}}DetectingInformationandStartingtheThreadNow,wemustwaitonthethreaduntilactivityoccurs.Oncewedetectsomesemblanceofinformationcomingacrossthesocket,wemustspawnathreadautomaticallyandletthethreadgetandprocesstheinformation.Ourmainprogrammerelydelegatesactivitytoothers.importjava.net.*;importjava.io.*;importjava.lang.*;importjava.util.*;publicclassPizzaServer{publicstaticvoidmain(Stringargs[]){//initializethenetworkconnectiontry{ServerSocketserverSocket=newServerSocket(8205);//nowsitinaninfiniteloopuntilwegetsomethingwhile(true){//acceptthemessageSocketincoming=serverSocket.accept();//spawnathreadtohandletherequestPizzaThreadpt=newPizzaThread(incoming);pt.start();}} catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}//threadedpizza!classPizzaThreadextendsThread{//thesocketwearewritingtoSocketincoming;PizzaThread(Socketincoming){this.incoming=incoming;}//runmethodimplementedbyThreadclasspublicvoidrun(){}}Noticealsohowwemustcallthestartmethodexplicitlyonthethread.AswediscussedintheThreadssectionofChapter1,ifaclassinheritsfromtheJavaThreadclass,thethreadmustbestartedfromoutsidetheclass.GatheringInformationOncethethreadisrunning,itneedstogotothesocketandgetinformation.Todoso,wemustobtaininputandoutputstreamstoreadandwriteto/fromthesocket.Rememberthatthesocketismerelyaconstruct.Inordertogetinformationfromit,itmustbeabstractedintoaninput/outputmechanism.Wewillthenbeabletoreadandwritetothesocket.Aswewilldiscussinourclientsection,thedatawearegoingtoreceiveisinabar-delimitedformat.WemustuseaStringTokenizerobjecttoextracttheinformationfromthemessage.importjava.net.*;importjava.io.*;importjava.lang.*;importjava.util.*;publicclassPizzaServer{publicstaticvoidmain(Stringargs[]){//initializethenetworkconnectiontry{ServerSocketserverSocket=newServerSocket(8205);//nowsitinaninfiniteloopuntil//wegetsomethingwhile(true){ //acceptthemessageSocketincoming=serverSocket.accept();//spawnathreadtohandletherequestPizzaThreadpt=newPizzaThread(incoming);pt.start();}}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}//threadedpizza!classPizzaThreadextendsThread{//thesocketwearewritingtoSocketincoming;PizzaThread(Socketincoming){this.incoming=incoming;}//runmethodimplementedbyThreadclasspublicvoidrun(){try{//getinputfromsocketDataInputStreamin=newDataInputStream(incoming.getInputStream());//getoutputtosocketPrintStreamout=newPrintStream(incoming.getOutputStream());//nowgetinputfromtheserveruntilitclosesthe//connectionbooleanfinished=false;while(!finished){StringnewOrder=in.readLine();//converttoareadableformattry{StringTokenizerstk=newStringTokenizer(newOrder,"|");Stringname=stk.nextToken();Stringaddress=stk.nextToken();Stringphone=stk.nextToken();intsize=Integer.valueOf(stk.nextToken()).intValue();inttoppings=Integer.valueOf(stk.nextToken()).intValue();//noexceptionwasthrownsocalculatetotalinttotal=(size*5)+(toppings*1); //sendtheresultbacktotheclientout.println("$"+total+".00");//putourresultonthescreenSystem.out.println("pizzafor"+name+"was"+totalString);}catch(NoSuchElementExceptionexc){finished=true;}}}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//closetheconnectiontry{incoming.close();}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}Noteinparticularthetwolinesweactuallyuseforreadinginformationfromthesocketandsendinginformationback:StringnewOrder=in.readLine();//sendtheresultbacktotheclientout.println("$"+total+".00");Thesetwolineshavethesamesyntaxastheywouldiftheywerereadingandwritingafile.Infact,aswediscussedinChapter1'sinput/outputsection,totheprogrammerasocketisnothingmorethanafile.Weareabletousestreams,readandwriteinformation,andsavesocketsjustaswewouldfiles.Thisisanimportantconcepttograspbecausethesecurityrestrictionsthatapplytosocketsalsoapplytofiles.WewilldiscusssecurityingreaterdetailinChapter13,"JavaandSecurity."TheTPOPClientClientsaretheenduserinterfacetoanapplicationandendupbeingresponsiblemainlyforcollectinguserinputandsendingittotheserver.Serversaretherecipientsofthatinformation.Thinkofaclientapproachingyourrestaurantwithapocketfullofmoneyandyoutheowner,astheserver,gladlyacceptingthatmoneyforyourproductandservices.Inthissectionwebeginourdiscussionofclient/serverprogrammingby developinganapplicationthattransmitsinformationacrossanetworkconnectiontoanotherprogram.DevelopingClientsforServersThePizzaToolweareabouttocreateisastand-aloneJavaapplicationandwillhaveafancyGUIinterfacethatyoucandesignyourself.OurGUIcode'sframeworklookssomethinglikethis:importjava.awt.*;importjava.net.*;importjava.io.*;publicclassPizzaToolextendsFrame{//AWTComponents...skipthesefornow...PizzaTool(){//initializetheapplicationframe//createtheGUIs}publicbooleanaction(Eventevt,Objectobj){if(evt.target==sendButton){}returntrue;}publicstaticvoidmain(Stringargs[]){PizzaToolpizza=newPizzaTool();pizza.show();}}Whendisplayed,ourpizzatoolGUIwilllooksomethingliketheoneshowninFigure3-1.Weneedtomodifythisworkingclienttosenditsinformationoverthenetworktotheotherend.Todoso,wemustcreateasocketinourapplication'sconstructorandinitializeitaswedidearlier.Wewilluseportnumber8205inthisapplication.importjava.awt.*; importjava.net.*;importjava.io.*;NOTEAswillbeourpracticethroughoutthisbook,weshowyouthecompletedGUIratherthanshowingthecodedevelopmentprocessforit.ThereareseveralGUIbuildersonthemarket,andwehopeyouwillchooseonetoassistyou.IfyouareaneophyteatJava,werecommendusingatexteditorandSun'sJDK(JavaDevelopmentKit)untilyoubecomeproficientatJava.GUIbuilderslikeVisualCafé,J++,andJBuilderaregreattoolsandcanreallyincreaseproductivity;theproblemisthattheyreallyhidealot(especiallyinbuildingtheuserinterface)fromyou.Insomecases,thecodeproducedbytheGUIbuildersisnotnecessarilygoodcode,butitiscodethatwillwork.publicclassPizzaToolextendsFrameimplementsActionListener{//AWTComponents...skipthesefornow...//networkcomponentsSocketsocket;DataInputStreaminStream;PrintStreamoutStream;PizzaTool(){//initializetheapplicationframe//createtheGUIs//defineExitbuttonhandler//defineResetbuttonhandle}publicvoidactionPerformed(ActionEvente){//handletheSubmitbuttonhere,buildandsendtheorder}publicstaticvoidmain(Stringargs[]){//usetheconstructortobuildtheGUIPizzaToolpizza=newPizzaTool();//showtheGUIandwaitforanActionEventpizza.show();}} InsidetheactionPerformedmethod,weneedtosendtheinformationwegatherfromourGUIbacktotheserver.Theserverthenmakesacalculationandsendsusthetotalfortheorder.First,wemustsendinformationacrossthesocketusingtheoutStreamvariablewederivedfromthesocket.Then,justaswedidearlier,wemustturnaroundandreadinformationfromthesamesocketusingtheinStreamvariable.importjava.awt.*;importjava.net.*;importjava.io.*;publicclassPizzaToolextendsFrameimplementsActionListener{//AWTComponents...skipthesefornow...//networkcomponentsSocketsocket;DataInputStreaminStream;PrintStreamoutStream;PizzaTool(){//initializetheapplicationframe//createtheGUIs//defineExitbuttonhandler//defineResetbuttonhandlerresetButton=newButton("ResetOrder");resetButton.setBounds(160,270,140,60);add(resetButton);resetButton.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvente){instructionField.setText("SelectPizza");nameField.setText("");addressField.setText("");phoneField.setText("");}});}publicvoidactionPerformed(ActionEvente){//handletheSubmitbuttonhere,buildandsendtheorder//createthesocketandattachinputandoutputstreamstry{//openthesockettotheremotehostsocket=newSocket("localhost",8205);in=newBufferedReader(newInputStreamReader(socket.getInputStream()));outStream=newPrintStream(socket.getOutputStream());}catch(Exceptione){ System.out.println(IOException:"+e.toString());}//SendtheordertotheserverinstructionField.setText("Sendingorder");try{outStream.println(nameField.getText()+"|"+addressField.getText()+"|"+phoneField.getText()+"|"+size+"|"+toppings);}catch(Exceptione){System.out.println("Error:"+e.toString());}//readthepricefromtheserverStringtotalString=newString();try{totalString=inStream.readLine();}catch(Exceptione){System.out.println("Error:"+e.toString());}}publicstaticvoidmain(Stringargs[]){//usetheconstructortobuildtheGUIPizzaToolpizza=newPizzaTool();//showtheGUIandwaitforanActionEventpizza.show();}}Pleasecheckoutthebold,italicizedtextthatdefinedtheResetbuttonanditseventhandler.Thislooksalittlestrangebutreallyisn't;whatyouarelookingatisananonymousinnerclassbeingusedastheeventhandler.WiththeneweventmodelthatcameaboutwithJDK1.1camesomeimprovedeventhandling.Usingananonymousinnerclass,theeventhandlercanbekeptrightwiththecode(thisaidsmaintainability)andeliminatestheneedforlargeif/then/elsestructuresfordecodingwhatcausedtheevent.Thismakesthecoderunconsiderablyfaster.Noticealsohowwesendinformationtotheserver.Wehavecreatedourownprotocolandmessageformattousetosendthethreeimportantcustomerfields,aswellasthekindofpizzaordered,directlytothepizzaserver.Theformatisdelimitedbythebarsign("|")and,aswewillseeinamoment,isinterpretedontheserverend.outStream.println(nameField.getText()+"|"+addressField.getText()+"|"+phoneField.getText()+"|"+size+"|"+ toppings);Oncecomplete,ourapplicationthenisabletopublishtheinformationitreceivedfromtheserver.NOTEInordertoconservepaper(savesometrees),wehavenotshownyoutheentirecodelistingforboththeGUIandthenetworkportionofourapplication.Asalways,afull,workingversionofthisapplicationcanbefoundontheCD-ROMthataccompaniesthisbook.Socketprogrammingisattheheartofeverythingwediscussinthisbook.Everycommunicationtechnologyinvolvedwithcomputersusessocketsinsomefashion.Often,havingcontrolovertheformatandlengthofmessagesbetweenclientsandserversisofgreatimportance.Wecouldjustaseasilyhavecreatedourpizzaapplicationusingamechanismfoundinotherpartsofthisbook.However,byusingsockets,wehadfullcontroloverhowthecommunication(protocol)isimplemented.ClientsandServersinShortSofarwehaveimplementedanapplicationforwhichweknowwhatisonbothends.Thisformofpoint-to-pointcommunicationisonewaytocreateanetworkedapplication.Wecreatedamessage,locatedthedestinationforthemessage,andshippeditoff.Whilereliable,point-to-pointcommunicationisimportant,wealsowanttobeabletoformamessageandbroadcastit.Insodoing,anyoneanywherecangrabthemessageandactonit.ThisformofbroadcastcommunicationcanalsobeaccomplishedusingJavasocketsandisdiscussedinthenextsection.UDPClientWehavespokensofaraboutTCPcommunication,whichwehavementionedisapoint-to-point,reliableprotocol.Well,whatmakesanunreliableprotocol?Anunreliableprotocolisoneinwhichyousendachunkofinformation,andifitgetslostalongtheway,nobodyreallyminds.TCPprovidesaninfrastructurethatensuresacommunicationissentandarrivessafely.Anotherprotocol,UserDatagramProtocol(UDP),isa"spitinthewind"protocol.Oneday,youwakeup,spitintothewind,andhopeitwilllandsomewhere.Likewise,withdatagramsyoucaneasilyformamessage,sendit,andhopeitgetstotheotherend.Therearenoguaranteesthatitwilleverarrive,sobecarefulwhenchoosingtouseaUDPsocketoveraTCP-basedsocketforyourapplication.DatagramsInthelastchapter,wereferredtodatagramsaslettersthatwesendtoamailbox.Infact,adatagramisachunkofmemory,notunlikealetter—achunkofpaperinto whichweputinformationandsendofftoamailbox.JustaswiththeU.S.PostalService,thereisabsolutelynoguaranteethattheletterwilleverarriveatitsdestination.Here'sasample"receivebuffer"datagram:DatagramPacketpacket=newDatagramPacket(buf,256);Youmustgivetheconstructorthenameofabyteorcharacterarraytoreceivethedataandthelengthofthebufferinbytesorcharacters.Yougetdataasfollows:socket.receive(packet);wheresocketiscreatedasfollows:socket=newDatagramSocket();TheDatagramSocketclassisanendpoint(mailbox)forUDPcommunication.LiketheSocketclass(whichusesTCP),thereisnoneedforaprogrammertospecifythetransport-levelprotocoltouse.Afteradatagramisreceived,youcanfindoutwhereitcamefromasfollows:address=packet.getAddress();port=packet.getPort();andyoucanreturnareplyasfollows:packet=newDatagramPacket(buf,buf.length,address,port);socket.send(packet);ThisdatagramwillgooutthesameUDPport(akintoa"mailbox"),totheotherprocess-receivingdatagramsonthatUDPportnumber.AUDPservercanspecifyitsserviceportnumberinitsconstructor,inthiscaseportnumber31543.socket=newDatagramSocket(31543); NOTEDatagramsaresortoflikethatold"ILoveLucy"episodeinwhichLucyandEthelgotoworkinacandyfactory.Astheystandinfrontofaconveyorbelt,littlecandiesbegintoflowout.LucyandEthelareabletowrapandpackagethecandiesastheycomeout.Soon,theirbossspeedsupthebelt,andthecandiesbegintoflowoutreallyfast;LucyandEthelareunabletokeepup.Similarly,datagramshappenalongtheportandarepickedupbyreceiverprogramsthathappentobelistening.UnlikeLucyandEthel,however,ifyoumissone,nothingbadwillhappen.CreatingaUDPSenderTopayhomagetoLucyandEthelinourownbizarre,twistedway,let'screateacookiefactory!Inourfactory,wewillbeabletobuildchocolatechipcookiesandspecifythenumberofchipswewantineachone.ThenwewillsendthemalongtheconveyorbelttobepackagedandshippedofftosomeJavaengineerturnedwriterwhoisindesperateneedofaScoobySnack.Real-worldimplementationsofbroadcastcommunicationincludestocktickersthatconstantlypublishstockquotesforNASDAQortheNewYorkStockExchange.Bysimplypluggingyourreceiverintotheport,youcangrabthatinformationanddosomethingwithit(likedisplayingitasatickertapemessageacrossthebottomofyourscreen).Modifyingoursampleprogramtosimilarlybroadcastandgrabinformationisquitesimple.Tobeginoursenderprogram,wemustcreateaJavaapplicationforourCookieBakery.TheapplicationwillhaveasimpleGUIinwhichyoucanspecifythenumberofchipsinthecookieusingasliderandthensimplypressabuttontosendthecookietotheconveyorbelt.TheGUIframeworklookslikethis:importjava.awt.*;importjava.net.*;publicclassCookieBakeryextendsFrame{//AWTcomponentsCookieBakery()//constructor{//initializetheapplicationframe//buildtheGUIandeventhandlerssendButton=newButton("SendCookie");sendButton.setBounds(10,270,290,60);add(sendButton);sendButton.addActionListener(newActionListener() {publicvoidactionPerformed(ActionEvente){//determinethenumberofchipsintnumChips=chipsScrollbar.getValue();StringmessageChips=numChips+"chips";//buildthemessageandsendit//displayfinalresultinstructionField.setText("SentCookiewith"+numChips+"chips!");}}//alleventshandledbyinnerclasses,thisisrequiredpublicvoidactionPerformed(Evente){;)publicstaticvoidmain(Stringargs[]){CookieBakerycookies=newCookieBakery();cookies.show();}}TheGUIitselfwillresemblethatshowninFigure3-2withaslidertoselectthenumberofchipsandabuttontopresssothatyoucan"bake"it.Figure3-2.SampleGUIfortheCookieBakery.FormattingaUDPPacketInordertosendapackettotheserver,wemustcreateandformatone.Packetsarecreatedusingbuffersandcontainanarrayofbytes.Therefore,anystringmessagethatyouwishtosendmustbeconvertedtoanarrayofbytes.Wewilldothisinamoment. Also,weneedtodefineandobtaintheInternetaddressofthemachineonwhichthisapplicationruns.UDPrequiresitaspartofitsprotocol.importjava.awt.*;importjava.net.*;importjava.awt.event.ActionListener;importjava.awt.event.ActionEvent;publicclassCookieBakeryextendsFrame{//AWTcomponentsCookieBakery()//constructor{//initializetheapplicationframe//buildtheGUIandeventhandlerssendButton=newButton("SendCookie");sendButton.setBounds(10,270,290,60);add(sendButton);sendButton.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvente){//determinethenumberofchipsintnumChips=chipsScrollbar.getValue();StringmessageChips=numChips+"chips";//convertthechipmessagetobyteformintmsgLength=messageChips.length();byte[]message=newbyte[msgLength];message=messageChips.getBytes();//sendamessagetry{//formatthecookieintoaUDPpacketinstructionField.setText("SendingCookie…");DatagramPacketpacket=newDatagramPacket(message,msgLength,internetAddress,8505);//sendthepackettotheserverDatagramSocketsocket=newDatagramSocket();socket.send(packet);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//displayfinalresultinstructionField.setText("SentCookiewith"+numChips+"chips!");}} publicvoidactionPerformed(Evente){;}publicstaticvoidmain(Stringargs[]){CookieBakerycookies=newCookieBakery();cookies.show();}}}SendingthePackettotheServerInordertosendthecookietotheconveyorbelt,wemustcreateaDatagramSocket.Thenwecansendthepacketwejustcreatedusingthesendroutine.importjava.awt.*;importjava.net.*;importjava.awt.event.ActionListener;importjava.awt.event.ActionEvent;publicclassCookieBakeryextendsFrame{//AWTcomponentsCookieBakery()//constructor{//initializetheapplicationframe//buildtheGUIandeventhandlerssendButton=newButton("SendCookie");sendButton.setBounds(10,270,290,60);add(sendButton);sendButton.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvente){//determinethenumberofchipsintnumChips=chipsScrollbar.getValue();StringmessageChips=numChips+"chips";//convertthechipmessagetobyteformintmsgLength=messageChips.length();byte[]message=newbyte[msgLength];message=messageChips.getBytes();//sendamessagetry{//formatthecookieintoaUDPpacketinstructionField.setText("SendingCookie…");DatagramPacketpacket=newDatagramPacket(message,msgLength,internetAddress,8505);//sendthepackettotheserver DatagramSocketsocket=newDatagramSocket();Socket.send(packet);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//displayfinalresultinstructionField.setText("SentCookiewith"+numChips+"chips!");}}publicvoidactionPerformed(Evente){;}publicstaticvoidmain(Stringargs[]){CookieBakerycookies=newCookieBakery();cookies.show();}}}Nowthatwehavecreatedanapplicationthatsendsamessagecontaining"xxchips"toaport,weneedsomethingontheotherendtoreceiveanddecodethemessageintosomethinguseful.Afterall,wedon'twanttowasteourdeliciouschocolatechipcookies!CreatingaUDPReceiverTheUDPReceiverwewillcreatewilllisteninonaportandwaitforcookies.Whenitgetsone,ourCookieMonsterwillletusknowbyprintinga"Yummy,tastesgood"message.AswithourCookieBakery,theCookieMonsterwilllisteninonport8505,atotallyrandomselection.TostartourCookieMonster,firstwemustcreatetheCookieMonsterobjectwithitsownapplicationmaincontainingthepacketthatwewillreadandthesocketfromwhichwewillgetit.Notethatweareimportingthejava.net.*packageonceagain.NOTEWefindthroughoutthisbookthatservers,inthiscaseareceiver,mustbeapplications,whereasclientsveryeasilycanbeappletsaswell.ThereasonisthatJava'ssecuritymechanismwillnotallowadownloadedapplettohaveunlimitedaccesstoaportonthemachinetowhichitisdownloaded.BecauseoftheJavasecuritymodel,youarepreventedfromdevelopingdownloadableservers.Thismaychangewiththeintroductionofbrowsersthatareabletochangethosesecurityrestrictions. importjava.awt.*;importjava.net.*;publicclassCookieMonster{publicstaticvoidmain(Stringargs[]){//oursocketDatagramSocketsocket=null;//ourpacketDatagramPacketpacket=null;}}Nowwemustcreateandinitializethepacketthatwewillreceive.Notethatwehavetospecifyabufferintowhichthepacketwillreadthemessage.Apacketbyitselfiscomposedoffourelements.Thefirstisshowninthefollowingcode.importjava.awt.*;importjava.net.*;publicclassCookieMonster{publicstaticvoidmain(Stringargs[]){//oursocketDatagramSocketsocket=null;//ourpacketDatagramPacketpacket=null;//createareceivebufferbyte[]buffer=newbyte[1024];//createapackettoreceivethebufferpacket=newDatagramPacket(buffer,buffer.length);}}Onceourpacketisputtogether,weneedtositonasocketandwaitforsomeonetofillitwithinformation.WeusetheDatagramSocket'sreceiveroutinetohangonaUDPportandgetinformation.Wemustpassthepackettothesocketsreceivemethodsothatthepacketknowswheretoputtheinformationitgets.importjava.awt.*;importjava.net.*;publicclassCookieMonster {publicstaticvoidmain(Stringargs[]){//oursocketDatagramSocketsocket=null;//ourpacketDatagramPacketpacket=null;//createareceivebufferbyte[]buffer=newbyte[1024];//createapackettoreceivethebufferpacket=newDatagramPacket(buffer,buffer.length);//nowcreateasockettolistenintry{socket=newDatagramSocket(8505);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//nowsitinaninfiniteloopandeatcookies!while(true){//sitaroundandwaitforanewpackettry{socket.receive(packet);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}}}Sonowwehaveacookieinourhands,andwehavetosomehoweatit.Todoso,wemustfirstextractthecookiefromthepacketbyretrievingthepacket'sbuffer.CAUTIONBecausewespecifiedthebuffersizewhenwecreatedthepacket,theCookieMonsterwaitsuntilthebufferisfilledbeforeitreturnsthepacket.Thismeansthatifthepacketsonthesendingendaresmallerthanthepacketswearereadinghere,wewillendupwithapacket,plusalittlebitofthepacketthatcomesdownthepikeafterwards,causinghavocinourmessagingsystem.Ifourbufferistoolargeonthesendingend,wewillreceiveonlyalittlebitofthemessage.Itisimportantthatyousynchronizeboththereceiverandthesendersothattheyreceiveandsendthesamesizebuffer. importjava.awt.*;importjava.net.*;publicclassCookieMonster{publicstaticvoidmain(Stringargs[]){//oursocketDatagramSocketsocket=null;//ourpacketDatagramPacketpacket=null;//createareceivebufferbyte[]buffer=newbyte[1024];//createapackettoreceivethebufferpacket=newDatagramPacket(buffer,buffer.length);//nowcreateasockettolistenintry{socket=newDatagramSocket(8505);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//nowsitinaninfiniteloopandeatcookies!while(true){//sitaroundandwaitforanewpackettry{socket.receive(packet);}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//extractthecookieStringcookieString=newString(buffer,0,0,packet.getLength());//nowshowwhatwegot!System.out.println("Yummy!Gotacookiewith"+cookieString);}}} Nowthatwehavelearnedhowtocreatepoint-to-pointandbroadcastcommunicationmechanisms,let'sapplyourknowledgetoimplementourfeaturedapplication.Inthisreal-worldscenario,wemustcreateamechanismthatenablesaclienttochangeitsstateandtosendthatinformationtoaservertobestoredandretrievedatalaterdate.Todevelopsuchanapplication,weneedapoint-to-pointprotocolbecausereliabilityisoftheutmostpremium.Afterall,wedon'twanttoscheduleanappointmentandnotknowifitactuallygotonourcalendar.FeaturedApplicationAswediscussedinChapter1,"AdvancedJava,"wewillreimplementthesame"featuredapplication"inthischapterandineachofthenextfourchapters.Wehopethatthisgivesyouaninsightintotheadvantagesanddisadvantagesofeachofthemajorcommunicationalternativesthatwepresentinthisbook.Oursocketimplementationneedstobeprecededbyadiscussiononhowweplantoimplementmessagingbetweentheclientandtheserver.Oncethatiscomplete,wecanimplementtheclientandtheservertoexchangeinformationinthatformat.MessagingFormatOurmessagingformatmustincorporatethetwomajorelementscontainedinournotionofanappointment—thetimeoftheappointmentandthereasonfortheappointment.Therefore,wewillcreateamessageformatakintothePizzaTool'smessage.InthePizzaToolweimplementedafewsectionsago,wedelimitedourmessagewiththebarsymbol("|").Onceagain,wewillusethebarsymboltoseparatethetimeandreasoninourmessagefromtheclienttotheserver.Fromtheservertotheclient,weneedaslightlysimilarbutmorerobustformat.Whentheserversendsinformationtotheclient,wewillneedtostringavariablenumberofbar-delimitedappointmentstogether.TheclientcanthenusetheStringTokenizerobjecttoextracttheinformationitneeds.But,theclientcannotacceptmessageswithoutaskingforthemfirst.Therefore,weneedaheadertothemessage.Whenwescheduleanappointment(i.e.,sendamessagefromtheclienttotheserver),weprecedethemessagebytheword"store."Whenwemerelyprompttheservertosendtheclientamessage(i.e.,theclientsendsamessagetotheservertellingittogoaheadandreply),weprecedethemessagewiththeword"retrieve."Therefore,ourmessagewillbeinoneofthefollowingtwoformats:store|TakeFleagletodentist|1retrieveTheretrievemessagepromptstheservertosendamessagebackwithappointmentsstrungtogetherbutdelimitedbythebarsymbol.Client BecauseimplementingtheclientforthefeaturedapplicationisquitesimilartothePizzaTool'sclient,thecodeweareabouttoproducewilllookremarkablysimilartothecodeforthePizzaTool.InordertoplugourfeaturedapplicationsocketimplementationdirectlyintotheCalendarManager,wemustimplementtheNetworkModulethatwedeclaredinChapter1.publicclassNetworkModule{publicvoidscheduleAppointment(Stringreason,inttime);publicVectorgetAppointments();publicvoidinitNetwork();publicvoidshutdownNetwork();}Specifically,weneedtoimplementthescheduleAppointmentsandgetAppointmentsmethods.Wewillalsohavetocreateandimplementaconstructortoopenandestablishthesocketconnection.Wewillfirstimplementtheconstructor.ThecodeisbasicallycutandpasteddirectlyfromthePizzaTool:importjava.awt.*;importjava.util.*;importjava.net.*;importjava.io.*;publicclassNetworkModule{//networkcomponentsSocketsocket;DataInputStreaminStream;PrintStreamoutStream;NetworkModule(){try{socket=newSocket("localhost",8205);inStream=newBufferedReader(newInputStreamReader(socket.getInputStream()));outStream=newPrintStream(socket.getOutputStream());}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}publicvoidscheduleAppointment(StringappointmentReason,intappointmentTime){} publicVectorgetAppointments(){}publicvoidinitNetwork(){}publicvoidshutdownNetwork(){}}NowwemustimplementthescheduleAppointmentmethodthatgoestotheserverwithaformattedmessagecontainingthenewappointment.Noticehowweputtogetherthemessagesothatitconformstothemessagingformatwejustagreedupon.publicvoidscheduleAppointment(StringappointmentReason,intappointmentTime){try{outStream.println("store|"+appointmentReason+"|"+appointmentTime+"|");}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}}Onceagain,theStringTokenizercomestoourrescueaswebegintodecodetheserver'smessagetousinthegetAppointmentsmethod.Inorderfortheservertosendusamessage,wemustpromptittodoso.Thatway,asocketconnectionisestablished,andareplycanbesentalongthesameroute.Itisn'tentirelynecessarytodothingsthisway,butitisthepreferredandtime-honoredmethod.Oncewegetourstringfromtheserver,wemusttokenizeit,stepthrougheachfield,andconvertitintoaVector.publicVectorgetAppointments(){//thevariabletostoreallofourappointmentsinVectorappointmentVector=newVector();//thestringtoputourappointmentsinStringappointmentString=newString();//nowgettheappointmentstry{//telltheserverwewanttheappointmentsithas outStream.println("retrieve|");//nowlistenforalltheinformationwegetbackappointmentString=inStream.readLine();}catch(Exceptionexc){System.out.println("Error!-"+exc.toString());}//tokenizethestringStringTokenizerstk=newStringTokenizer(appointmentString,"|");//translateintoaVectorwhile(stk.hasMoreTokens()){//createavariabletosticktheappointmentinAppointmentTypeappointment=newAppointmentType();//nowgetthenextappointmentfromthestringappointment.reason=stk.nextToken();appointment.time=Integer.valueOf(stk.nextToken()).intValue();//puttheappointmentintothevectorappointmentVector.addElement(appointment);}//returntheVectorreturnappointmentVector;}ServerToimplementtheserver,wewillblatantlyplagiarizecodefromthepizzaapplicationearlierinthischapter.Basically,wetakealltheservercodefromthere,includingthethreadportion,andmodifyitforourneeds.First,weneedtoimplementtheStoremethod.WewillstoreourappointmentsinaVectorforsimplicity'ssake.ThecodesnippetthatfollowsisfromtheRunmethodoftheCalendarThread.NOTEYoucouldjustaseasilyusesomekindofserializationorevenafiletokeepyourappointmentspersistent.Whentheservershutsdown,wewilllosealltheappointmentsinourcurrentimplementation.Ourserverkeepsdatainatransientstate,meaningthatitisnotmaintainedbetweenexecutions.//converttoareadableformattry{StringTokenizerstk=newStringTokenizer(newOrder,"|");Stringoperation=stk.nextToken();if(operation.equals("store")){Stringreason=stk.nextToken();inttime= Integer.valueOf(stk.nextToken()).intValue();//noexceptionwasthrownsostoretheappointmentAppointmentTypeappt=newAppointmentType();appt.reason=reason;appt.time=time;appointmentVector.addElement(appt);//putourresultonthescreenSystem.out.println("stored"+reason+"|"+time);}}catch(NoSuchElementExceptionexc)Nowwemustimplementtheretrievefunction.Theretrievefunctioncreatesanewstring,delimitedbythebarsymbol,ofcourse,thatcontainseveryappointmentinourVector.Itthensendsthatinformationbacktotheclientusingthesamesocketonwhichitreceivedtheoriginalmessage.else{StringreturnValue=newString();//puttogetherastringofappointmentsfor(intx=0;x:.Thesubprotocolisakindofconnectivitytothedatabase,alongthelinesofODBC,whichweshalldiscussinamoment.Thesubnamedependsonthesubprotocolbutusuallyallowsyoutoconfigurethedatabasethattheapplicationwilllookat.DatabaseStatementObject.AStatementencapsulatesaquerywritteninStructuredQueryLanguageandenablestheJDBCobjecttocomposeaseriesofstepstolookupinformationinadatabase.UsingaConnection,theStatementcanbeforwardedtothedatabaseandobtainaResultSet.ResultSetAccessControl.AResultSetisacontainerforaseriesofrowsandcolumnsacquiredfromaStatementcall.UsingtheResultSet'siteratorroutines,theJDBCobjectcanstepthrougheachrowintheresultset.IndividualcolumnfieldscanberetrievedusingthegetmethodswithintheResultSet.Columnsmaybespecifiedbytheirfieldnameorbytheirindex. JDBCandODBC.Inmanyways,OpenDatabaseConnectivity(ODBC)wasaprecursortoallthatJDBCisintendedtoaccomplish.Itadequatelyabstractstheboringtediumofdatabases,andtheproprietaryAPIstothosedatabases,fromtheapplicationprogrammer;ittiesmanydifferentkindsofdatabasestogethersothatyouonlyhavetocreateonesourcefiletoaccessthem;anditisfairlyubiquitous.RecognizingtherelativeacceptanceofODBCtechnology,JDBCoffersaJDBC-to-ODBCdriverfreewiththeJDK.Withthis,JDBCapplicationscantalktothesamedatabaseaccessengineasnon-Javaapplications.Furthermore,integratingJDBCintoyourexistingbusinessprocesscanbedonefairlyeasilybecausethebridgeensuresthatnoadditionalworkisrequiredtoenableJavaDatabaseConnectivity.NOTEBecauseofcopyrightrestrictions,weareunabletosupplythesedriversontheCD-ROM,butyoumayvisittheJDBCpageontheJavaSoftWebsiteatjava.sun.com/jdbcandgetthelatestinformationondriversandthepointerstothem.Asyoucansee,theJDBCapplicationcommunicateswiththedatabaseusingthesameexistingOLEorCOMprotocol.Furthermore,anyadministrationissuesassociatedwiththedatabasearenegligiblebecausetheexistingadministrationstrategyisstillapplicable.ApplicationprogrammersneedknowonlythattheODBCbridgewillbeusedandthattheyshouldnottailortheirapplicationtoit.InstallingtheODBCdriverforWindowswillbediscussedinthenextsection.BecauseitisaMicrosoftproduct,theprocessiseasy,butthereliabilityisindoubt.Keepinmindthatmostmission-criticalapplicationsarerunusingheavy-duty,workstation-baseddatabases.ThesedatabasesareexpensiveanddifficulttoadministerbuttheyaremorereliablethanaMicrosoftAccesssolution.Inanyevent,wewillshowyouhowtowriteapplicationstailoredforMicrosoftbecausethegeneralcomputingpopulace,andmoreimportantlytheaudienceofthisbook,willnotnecessarilyhaveaccesstodatabaseserverslikeSybase,DB2,orOracle.JDBCinGeneralJavaDatabaseConnectivityencapsulatesthefunctionalityofdatabasesandabstractsthatinformationfromtheenduserorapplicationprogrammer.CreatingsimpleJDBCapplicationsrequiresonlyminorknowledgeofdatabases,butmorecomplexapplicationsmayrequireintensivetrainingindatabaseadministrationandprogramming.Forthatreason,wehavechosenseveralsimpleandfunexamplestodisplaythepowerofaJavasolutionthatwillmorelikelythannotbeusedbymission-criticalapplications.SofarwehaveonlyaddressedtheuseofJDBConWindows-basedplatforms.We,asapplicationdevelopersandarchitects,shouldn'tlosesight ofthefactthatJDBCworksonanyplatformthatsupportstheversion1.1(ornewer)JavaVirtualMachine.ThisincludesmanyUNIXplatformsfromIBM,Sun,andHPtonameafewandmainframecomputerslikeIBM'sOS390,VM/CMSanditsmidrangeOS/400-basedcomputers.OnalltheseplatformsJDBCprovidesaconsistentinterfacetorelationaldatabasesnativetotheseplatforms.AlmostallmodernrelationaldatabasemanagementsystemsprovideTCP/IP-basedaccesstotheirdatastoresviaSQL.ThisgivesusasenterpriseapplicationdevelopersconnectivityfromvirtuallyanyJava-basedclienttoanyrelationaldatabaseonanyhostplatform.DatabasesandSQLDatabasesarestoragemechanismsforvastquantitiesofdata.Anentiresegmentofthecomputerindustryisdevotedtodatabaseadministration,perhapshintingthatdatabasesarenotonlycomplexanddifficultbutalsobestlefttoprofessionals.BecauseofthislevelofdifficultyandofourdesiretogetyoustartedinlinkingJavatodatabases,wehavechosentoimplementawidelyavailable,easilyadministered,andsimplyinstalleddatabase.MicrosoftAccesscanbepurchasedatyourlocalsoftwareretailer.Ifyouwanttogetstarted,it'sagoodplacetostart.Fromthere,youcanmoveontomorecomplexdatabasessuchasOracleandSybase.Inthissection,weintendtointroduceandcreateasimpledatabase.Inthenextsection,youwillcreateasimpleJavaclientthataccessesthedatabaseandgetsinformationfromit.WesuggestthatfurtherexplorationintoJDBCbeprecededbyaseriousinvestigationintoSQL(anyofthecurrentlyavailabletextsonRelationalDatabaseManagementSystemswillsuffice;checkAmazon.comforcurrentlyavailabletexts).TheStructuredQueryLanguageenablesyoutocreatepowerfulinstructionstoaccessdatabases.OnceyougraspSQL,youwillbeabletounderstandthereasoningandtheoriesbehindJDBC.CreatinganAccessDatabaseWewillneedtofirststartMicrosoftAccesssothatwecancreateadatabasetotalkto.Thisisanimportantstep,butonethatthosewhoeitherdonothaveaccesstoorwhodonotwishtouseMicrosoft'sdatabasecantailorfortheirowndatabase.AfterstartingAccess:1.Select"DatabaseWizard"soAccesswillhelpyoucreateadatabase.2.Selectthe"BlankDatabase"icon.3.Namethedatabaseandthenyouwillgetaseriesoftabbedfolders.Goto"Tables"andclickon"New."4.Youwillgetaspreadsheet-likeviewinwhichyoucanenteryourdata.5.EnteryourdataasshowninFigure4-7andthenselect"Save"tostorethetabletothedatabase.NameyourtablePresidentialCandidate.Figure4-7.Ourdatabaseentry. AsyoucanseeinFigure4-7,weenteredtheimportantstatisticsfromthelastpresidentialelection.Thepercentageisstoredasawholenumber,notasadecimal.Thisallowstheapplicationtodeterminehowitwillrepresenttheinformation.Wealsostoretheelectoralvotesthateachcandidatereceived.SimpleSQLNowthatwe'veputthestatisticaldataaboutthecandidatesintoourdatabasetable,wecanuseAccesstohelpusdesignthequeriesthatwewillneedforourGUI.Todoso,weneedtoknowalittlebitofSQL.Thisisbynomeansintendedtobethebe-allandend-allofSQLtutorials.ThisisaJavabook,andassuchwewillminimizeourdiscussionofSQL.Sufficeittosaythat,foraprogramminglanguagethathasnoprogramcontrolstatementsandiscompletelydeclarative,itisextremelypowerful.ThemostoftenusedinstructioninSQListheSelectstatement.Selectenablesyoutoretrieveacopyofspecificportionsofadatabasetable.AspartoftheSelectstatement,youmustspecifyboththedatabasetablefromwhichyouwanttheinformationandafilterfortheinformation(ifrequired).So,whenyouSelectFromatableWheretheparametersmatchyourrequirements,yougetaresultback.SELECTcolumnlistFROMmyTableWHEREfilterTheWhereclauseoftheSelectstatementmaycontainwhatisknownasafilter.Filtersarespecifiedasconditionalsandenableyoutofurthertailorthematchparametersforadatabasequery.Inamoment,wewillqueryadatabasetableforallthepresidentialcandidateswhoreceivedelectoralvotesinthe1996election.Fromafieldofthreecandidates,wewillendupwithtwo.Bigpartypoliticsaside,ourquerywillreturnaresultbasedontheparameterswespecify. Intheory,thatresultalwayswillbeadatabasetableofitsown.Forexample,giventhefollowingtableofpresidentialelectionresultsandtheaccompanyingSQLstatement,wewillreceiveatableinreturn(seeFigure4-8).Figure4-8.SQLstatementcanbemadetoreturnentiretables.Thistableislikealocalvariable.Itdisappearsfrommemoryifwedon'tuseitrightaway.UsingJDBC,thisresultstableissavedforustoretrievetheresultsdatafromanobjectcalledaResultSet,whichwillgoaway(begarbagecollected)whentheobjectgoesoutofscope.WecouldjustaseasilyincludethisSQLstatementwithinanotherSQLstatementandachievepredictableresults.ThesearecalledsubqueriesandareanotherpowerfultoolofwhichSQLprogrammerscantakeadvantage.ThebeautyofSQLisitssimplicity.Obviously,alanguageofsuchgreatimportancehasseveralnuancesthatdatabaseexpertshavelongknown,butitisstillfairlyeasytostartwritingSQLstatements,aswewilldiscoverinthischapter.GeneratingSQL.InordertocreatethenecessaryqueriesforourAccessdata,wemustdothefollowingsteps.ThiswillletuscallthesesuperqueriesratherthanbeingforcedtospecifySQLinourJavacode.Thereareadvantagesanddisadvantagestothisapproach,whichwewilldiscussinamoment.1.Selectthe"Queries"tabinthemaindatabaseview.2.Select"New."3.Select"DesignView."4.Immediatelyselect"Close"inthe"ShowTable"view.5.Gotothe"Query"menuandselect"SQLSpecific"andthen"Union."Nowwearepresentedwithalittletextinputareainwhichwecanenterourquery.Usingthelimitedamountofinformationwehavejustlearned,wemustcreatethreequeries,oneforeachcandidate,thatwillretrievetheimportantstatisticsforus.WehaveshowntheClintonQueryinFigure4-9,andyoucanseewhatyourdatabasewilllooklikewhenallthreequeriesarecompleted.Figure4-9.GettingstatisticsonBillClintonfromthedatabase. Notethatwehavelimitedthenumberofqueries.Youcouldjustaseasilycreatemorecomplexqueries,andifyouknowSQLprettywell,weencourageyoutodoso.Otherwise,itisprobablybesttogetthis"proofofconcept"exampledownpatbeforeproceeding.IntroductiontotheODBCDriver.Oncethedatabaseiscompleted,wemustmakeitavailableviathedatabaseserver.Todoso,wemustedittheODBCControlPanel.TheODBCControlPanelassignsourdatabasetothedriver,allowinginvocationsonthedatabasetopassthroughthedriverrightintothedatabase.UnlessthedatabaseismadepublictotheODBCdriver,thiscannothappenbecausethesystemwillnotknowaboutthedatabase'sexistence.Toassignthedatabasetothedriver,selectthedriverControlPanel.TheControlPanelshouldhavebeeninstalledwithAccess.Ifitisnotthere,checkyourMicrosoftAccessinstallationinstructions.InsidetheControlPanel,select"MSAccess7.0"and"Select"theproperdatabasefromwithintheSetupdialogbox(seeFigure4-10).Figure4-10.StartingtheODBCdriver. Oncecompleted,theODBCdriverwillbeawareofthedatabaseyouhavecreatedandawaitinvocationsonit.Aslongastheincomingqueriesspecifythe"ElectionDatabase"database,theywillbedispatchedtothedatabaseandfromtheretoourSQLqueries.SummaryODBCisaproprietarydatabasemanagementprotocol.ItenablesyoutoaccessinformationondatabasesfromwithinMicrosoftWindows.OnceODBCissetuponourmachine,wecangetinformationfromthedatabasebycreatingJavaapplicationsthatinterfacetoit.OnethingtomakesurethatyourememberwhenusingAccesslikethisisthatAccessisapersonaldatabaseandnotafullblownrelationaldatabasemanagementsystemlikeOracle,DB2,andSQLServer.ThemdbfilethatAccessusesasitsdatastorageelementisjustafile,itistheODBCdriverthatmakesitlookandactlikeadatabase.RetrievingInformationAtfirstglance,youprobablywonderwherethe"server"partforthissectionis.Well,wecreateditwhenwecreatedourdatabase!Thedatabaseistheserver.ThebeautyofJDBCclientsisthattheylinkdirectlywithdatabases.Inclient-serverterms,thisisreferredtoasa"two-tier"modelinwhichtheclientisthefirsttierandthedatabaseitselfisthesecondtier.Intherestofthebookwewillpromotethethree-tiermodelinwhichclientsdonothingbutlookgoodandinterfacewithservers.Theserverscontainallthebusinesslogic,andthedatabasesonlystoredata.InJDBCandthetwo-tiermodel,theclientcontainsallthebusinesslogicandisresponsibleforcontactingandaccessingthedatabase.OurJDBCclientusesSQLqueriestocontactourMicrosoftAccessdatabase.Thedownsidetothisisthe complexityoftheclientandthescalabilityofthesystem.Withpotentiallyhundredsofclientsbangingonthesamedatabase,thedatabasecouldgetoverloaded.Withathree-tiermodel,thedatabaseisqueriedbyonlyoneapplication—theserver—andtheserverisresponsiblefor(andismorecapableof)handlinghundredsofsimultaneousrequests.Inanyevent,wewillpresentyouwithamorethoroughlookattheadvantagesanddisadvantagesofthetwo-andthree-tiermodelsinChapter14,"MakinganArchitecturalDecision."Inthissection,weshowyouhowtogotoadatabaseandgetinformation.Inthenextsection,wewillshowyouhowtoputinformationintothedatabase.CreatingtheUserInterfaceOuruserinterfaceshouldbesimpleandelegant.Onceagain,wedon'twanttoconfusepeoplewithwhatwearetryingtodo.Wewillcreateabuttonforeachcandidate.Uponactivationofthebutton,theclientwillexecuteSQLstatementsontheserverandgetinformation.Thenitwilldisplaytheinformationinthetextfieldsprovided.SeeFigure4-11forasampleGUI.Figure4-11.SampleGUIforthePresidentialElectionapplication.TheuserinterfacewillenableustounderscorethesimplicityofJDBC.Wehaveseenhowitcanhandlethemostcomplexofcases,buthereweonceagainkeepourexamplesfunandeasy.Asweproceed,wewillshowyouhowtoimplementthetwoimportantfunctionsinthisapplication.ThePresidentialElectionapplication'sconstructoranditscorrespondingactionmethodwillinitializeandinvokethedatabase,respectively.publicclassPresidentialElection{ButtonclintonButton;ButtondoleButton;ButtonperotButton; TextFieldpopularField;TextFieldelectoralField;PresidentialElection(){//createtheuserinterfacehere}publicvoidactionPerformed(ActionEvente){Stringarg=e.getActionCommand();if(arg.equals("Clinton")){}elseif(arg.equals("Dole")){}elseif(arg.equals("Perot")){}}}DatabaseSecurityBecausewearewritinganapplication,handlingourownsecurityisnotarequirement.However,ifwewantedtowriteanapplet,wewouldneedtouseaSecurity-Managertosetouraccesstothehostdatabase.BecauseJavaappletsareabletoconnectonlytotheirhostmachine,oursecuritymanagerisrequiredtomakesurewehaveaccesstothedatabaseonthehostmachine.Bysettingthesecuritymanager,youcanchecktoseeifyouhaveaccesstothedatabasebeforeaqueryisexecuted.KeepinmindthatthesecuritymanagerdealswithsecurityasitrelatestoJava.Databaseaccesssecurity(useridandpassword)ishandledthroughtheinstantiationoftheConnectionobject.UsingtheJDBCDriverAswediscussedearlier,wemustincludetheJDBCdriverinourapplication.Todoso,weobtainaConnectionobjectfromDriverManager.TheDriverManagertakesaURLandtranslatesitintoahandleforanactualdatabase.ThenwecaninvokeourSQLstatementsonthedatabaseandretrieveinformation.FromtheConnectionobject,wecanretrieveStatement,PreparedStatement,andCallableStatementobjectstohelpusformatourSQLqueries.AsJDBCgainsmoreacceptance,databasevendorswillprovidedriversforJavaapplicationstousetocontacttheirdatabases.Often,therewillbesomeoverlapbetweenthesedifferentdrivers.Choosingtheproperdrivercanbeadifficulttask,butJDBCenablesyoutocreateacolon-separatedlistofdriversthroughwhichJDBCwillsearchforthefirstavailabledriver.Here,wewillusethestandardODBCdriverincludedwithJDBC.ThiswillenableustoconnecttoODBCdatabasessuchastheMicrosoftAccessdatabasewejustcreated. AslongasourODBCdriverhasbeensetuptoawaitthiskindofquery,thiswillsucceed.Wewillneedtoloadthespecificclassforthedatabase"manually."importjava.sql.*;publicclassPresidentialElection{ButtonclintonButton;ButtondoleButton;ButtonperotButton;TextFieldpopularField;TextFieldelectoralField;//theconnectiontothedatabaseConnectiondbConnection;PresidentialElection(){//createtheuserinterfacehere//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:PresidentialCandidate";//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//maketheconnectiontothedatabasedbConnection=DriverManager.getConnection(url,"username""password");}publicvoidactionPerformed(ActionEvent2){Stringarg=e.getActionCommand());if(arg.equals("Clinton")){}elseif(arg.equals("Dole")){}elseif(arg.equals("Perot")){}}}AfterwecreatedtheURLrepresentationforourdatabase,weneededtoconnecttothedatabaseitself.Oncethatisdoneourapplicationislinkedtothedatabaseandcanmakeinvocationsatwill.CreatingQueriesNow,wemustfillintheactionPerformedsothatwecanmakethequeryonthedatabase.Here,wewillspecifytheSQLqueryrightintheexecuteQuerymethod.Wecouldalsodothisbyjustexecutingthequerieswecreatedandstoredinthedatabase itself.SincewemaybebeginnerswithJDBC,Ithinkitismoremeaningfultostartoutshowingthequeriesalongwiththecode.importjava.sql.*;publicclassPresidentialElection{ButtonclintonButton;ButtondoleButton;ButtonperotButton;TextFieldpopularField;TextFieldelectoralField;GubernatorialElection(){//createtheuserinterfacehere//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:GubernatorialCandidate";//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//maketheconnectiontothedatabaseConnectionconnection=DriverManager.getConnection(url,"username""password");}publicvoidactionPerformed(ActionEvente){Stringwho=newString("");Stringarg=e.getActionCommand();if(arg.equals("Clinton"))who="Clinton";elseif(arg.equals("Dole"))who="Dole";elseif(arg.equals("Perot"))who="Perot";elseSystem.out.println("Error");try{Statementstatement=dbConnection.createStatement();Strings="selectpercentage,electoral"+"fromPresidentialCandidate"+"wherecandidate='"+who+"'";ResultSetresult=statement.executeQuery(s);popularField.setText(who+""+result.getInt(1));electoralField.setText(who+""+result.getInt(2));}catch(SQLExceptionse){System.out.println("SQLError:"+se.toString());}}}InplaceoftheSelectstatement,wecouldjustaseasilyhaveexecutedthequerythatwehadearlierstoredinthedatabase.Asalreadymentioned,wechoosenottohelpimprovethelearningexperience. DatabaseandSQLOverviewOnceweareabletointerfacewiththedatabase,weshouldbeabletoputinformationinit.Databasesarenotstaticentities.Theyareeverchanging,andinkeepingwiththattrait,Javaprovidessomeprettycooltoolstogettodatabasesandchangethedatastoredtherein.StoringInformationJDBCalsogivesyouameanstostoreinformationinatable.Onceagain,thisisdoneusingstandardStructuredQueryLanguagestatements.ByusingSQL,JDBCmakessurethatitsownlearningcurveisprettysmall.JDBCgivesyoumuchflexibilityincreatingstatements.Let'ssaythatsuddenlywediscoverthatBillClintonisreallyDaffyDuck!The700,000peoplewhowrotein"DaffyDuck"ontheirballotastheirchoiceforPresidentoftheUnitedStatesreallyvotedforBillClinton.Asaresult,thepercentagebywhichBillClintonwonthe1996electionchanged.WeneedtocreateaJDBCquerytomodifythepercentage.CreatingtheConnectionThefirstthingwemustdoiscreatetheconnectionaswedidbefore.WewillalsoaddabuttontochangethepercentageofvotesforBillClinton.Wecouldwithaslightbitmorecomplicationandeffortcreateamorecustomizablechangearea.Itcouldhavetextfieldsforeachentryandasubmitbutton.Usingthedatainthetextfield,wecouldchangethedatainthetable.Fornow,however,thatismorecomplexthanisneeded.publicclassPresidentialElection{ButtonclintonButton;ButtondoleButton;ButtonperotButton;ButtonchangeButton;TextFieldpopularField;TextFieldelectoralField;PresidentialElection(){//createtheuserinterfacehere//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:PresidentialCandidate";//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//maketheconnectiontothedatabaseConnectionconnection=DriverManager.getConnection(url,"username""password");}publicbooleanaction( Eventevt,Objectobj){if(evt.target==clintonButton){...sameasbefore...}elseif(evt.target==doleButton){...sameasbefore...}elseif(evt.target==perotButton){...sameasbefore...}elseif(evt.target==changeButton){}}}Wealsoneededtoinsertevent-handlinginformationforthenewbutton.Asyoucansee,thereisnochangebetweentheconnectionforretrievinginformationandtheconnectionhereforsettingtheinformation.FormingaStatementTheburden,inJDBC,isplacedontheformationofstatements.Asdatabaseprogrammersexpect,thereisnoneedtolearnanythingneworconfusing.JavaistreatedasnothingmorethanacontainerforanSQLstatement.TheSQLstatementswecreatehereaswellaswhenwestoredinformationarenothingfancy,nothingspecial,andnomoreinterestingthananormalSQLstatement.Inordertochangetheinformationinadatabase,weneedtousetheSQLUpdatestatement.Wemustspecifyacolumnandrowtochange.But,insteadofencapsulatingtheSQLstatementwitharegularJDBCstatement,insteadwewilluseaPreparedStatement.PreparedStatementsgiveyoutheabilitytoinsertparameterswithinthestatementitself.Thefollowingexamplecontainstwoparameters,popularvoteandcandidate:UPDATEPresidentialCandidateSETpopularvote=?WHEREcandidate=?Thepopularvotefieldismarkedasfieldnumberone,andcandidateisfieldnumbertwo.Tosetthefields,weusethesetmethodssuppliedwithJDBCalongwiththenumberofthefieldyouwanttochange:setInt,setString,etc.Todefinethefields,usethequestionmark. NowwecancreateaPreparedStatement.Note,however,thatinthischapterwearenotusingprecreatedqueries.Instead,wewillcreatethequerydirectlyfromJDBC.Aswediscussedearlier,eitherapproachiscompletelyacceptable.Thechoiceisnotoneofeffortbutratherofprogrammingapproach.Ifyourbusinessmakesheavyuseofprecreatedqueries,obviouslyyouwillchoosetoinvokethemfromJDBC.Ifdatabaseinteractionisnotasimportant,thenthereisreallynoneedtodefinequeriesaheadoftime.publicclassPresidentialElection{ButtonclintonButton;ButtondoleButton;ButtonperotButton;ButtonchangeButton;TextFieldpopularField;TextFieldelectoralField;PresidentialElection(){//createtheuserinterfacehere//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:PresidentialCandidate";//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//maketheconnectiontothedatabaseConnectionconnection=DriverManager.getConnection(url,"username""password");}publicbooleanactionPerformed(ActionEvente){Stringarg=e.getActionCommand();if(arg.equals("Clinton")){...sameasbefore...}elseif(arg.equals("Dole")){...sameasbefore...}elseif(arg.equals("Perot")){...sameasbefore...}elseif(arg.equals("Change")){//createthestatementPreparedStatementpstate=connection.prepareStatement("UPDATEPresidentialCandidate"+"SETpopularvote=?"+"WHEREcandidate=?");//settheparametersforthestatementpstate.setInt(1,50);pstate.setString(2,"Clinton"); //executethestatementpstate.executeUpdate();}}}Nowthatwecancreateasimplesystemofclientsthatchangeinformationinadatabase,wecantrytocreateaclientforourfeaturedapplicationthatwillstoreandretrieveitsinformationfromasimilardatabase.Bycreatingthispurelytwo-tiermodel,itcanbecomparedtotheapplicationswecreatedinChapter3forusingsockets.AJDBCVersionoftheFeaturedAppAswehaveseenintheprevioussections,creatingaJDBCinterfacetoadatabaseisfairlyeasy.Thedifficultpartsinvolvesettingupthedatabaseandinstallingthedriver.Althoughwewon'tdiscussthefinerpointsofdriversordatabaseadministration,wewillcreatethedatabaseaswellastheinterfacetoit.CreatingtheDatabaseOnceagain,wewillcreatethedatabaseandassociatedqueriesusingMicrosoftAccessasshowninFigure4-12.Asbefore,ourdecisiontouseAccessisduelargelytoitsubiquityandeaseofuse.Wewantyoutobeabletocreateinterfacestodatabasesquicklyandeasily,andMicrosoftAccessprovidesasimplemeanstodoso.Aswithallthird-partyproducts,ifyourequireassistancewithAccess,contactMicrosoft.Inanyevent,ifyouhaveaccesstoSybase,Oracle,oranotherdatabase,feelfreetouseit.Youshouldnothavetomodifythecode,butyouwillhavetoinstalladriverforthedatabaseyouplantouse.Figure4-12.Ournewdatabase. Wewillstoreourappointmentsinthedatabaseusingtwokeys—thereasonfortheappointmentandthetimeoftheappointment.ThisconformstotheinterfacetotheNetworkmodule.Inamomentwewilldiscusshowtomapthenetworkmoduletothedatabase.Fornow,takealookattheAccesstableinFigure4-13.Figure4-13.Tableforourappointments.Wemustcreateourqueryeitherwithinthedatabaseorwithinourprogram(NetworkModule)togetappointmentstotheclientinterface.Mypreference,forthepurposeofthistext,istocodeitintotheprogram.Thisisn'tasefficientfromthestandpointofexecutionperformance,butitkeepseverythingintheNetworkModule.SELECTTIME,REASONFROMSCHEDULEORDERBYTIMEWe'llusetheORDERBYclauseoftheSELECTstatementtogetourappointmentsforthemorning,afternoon,andeveninggroupedtogetherlikearealappointmentschedulerwould.MappingtheNetworkModuletoDatabaseQueriesNowweneedtoconnectthenetworkmoduletothedatabase.Rememberthatadrivermustbeinstalledforthedatabase.Withoutitthedatabaseaccessqueriescannotfunction.Ournetworkmodule'sinterfacelookslikethis:publicclassNetworkModule{publicvoidscheduleAppointment(Stringreason,inttime);publicVectorgetAppointments();publicvoidinitNetwork();publicvoidshutdownNetwork();} Obviously,wewillmapthescheduleAppointmentmethodtoaPreparedStatementquery,butwewillmapthegetAppointmentmethodtotheGetAppointmentsquery.Wewillpassourconstructor'scodedirectlytotheinitNetworkmethod,andwemustcloseourconnectiontothedatabase(theshutdownNetworkmethodisthelogicalplacetoincludethatcode).DevelopingtheClientThemajorityofourclientapplicationwasdevelopedinChapter3,leavingustomodifytheNetworkModule.Doingsoisjustassimpleasbefore.Let'sfirsttakealookatthenetworkmodule'scodewithoutthemodifications.WemustincorporatetheJDBCclassesaswellastheclassesforthedriver.importjava.sql.*;publicclassNetworkModule{NetworkModule(){}publicvoidscheduleAppointment(Stringreason,inttime){}publicVectorgetAppointments(){}publicvoidinitNetwork(){}publicvoidshutdownNetwork(){}}Onceourclientisready,wemustfillintheinformationforeachfunction.First,wewillscheduleappointmentsusingthescheduleAppointmentquerythatwecreatedearlier.Essentially,thenetworkmoduleactsasapass-throughfromtherestoftheapplicationdirectlytothedatabase.Normally,wewouldtrytoincorporatesomekindofmiddlemantohandlethepass-throughfromourGUItothedatabase,butforsimplicity'ssakewewillnotdevelopathree-tierapplicationhere.Inthefuture,ifyoudesireathree-tierapplication,yourmiddle-tierserverwouldmakethesecalls.EstablishingtheConnection First,wemustcreatetheconnectiontothedatabaseandlinkournetworkmoduletoit.Thisensuresthatwehaveaclearpathtothedatabase.Anyerrorshereshouldbecaughtandthrownback.Wealsomustmakesuretoloadthedatabasedrivermanuallybyspecifyingitsentireclassname.importjava.sql.*;publicclassNetworkModule{//createtheconnectiontothedatabaseConnectiondbConnection;NetworkModule(){//initthenetworkconnectiontodbinitNetwork();}publicvoidscheduleAppointment(Stringreason,inttime){}publicVectorgetAppointments(){}publicvoidinitNetwork(){//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:Schedule";//maketheconnectiontothedatabasedbConnection=DriverManager.getConnection(url,"username""password");}publicvoidshutdownNetwork(){}}MakinganSQLInvocationInvokingthedatabaseisrelativelystraightforwardandnotunlikeourearlierinvocationofthePresidentialElectiondatabase.Here,wesubstituteourowninvocation.Thedifferenceinthisinvocation,however,isthatwewillretrieveacomplextypefromtheSQLquery.Asaresult,wemusttranslatethecomplextypeintotheVectorthatisexpectedasareturnvalueforthegetAppointmentsinvocation.importava.sql.*;publicclassNetworkModule {//theconnectiontothedatabaseConnectiondbConnection;NetworkModule(){//initthenetworkinitNetwork();}publicvoidscheduleAppointment(Stringreason,inttime){}publicVectorgetAppointments(){//createavectortopassbackVectorappointmentVector=newVector();try{//createthestatementStatementstatement=dbConnection.createStatement();Strings="SELECTTIME,REASON"+"FROMSCHEDULE"+"ORDERBYTIME";//gettheresultResultSetresult=statement.executeQuery(s));//walkthroughtheresultsetfortheinformationwhile(result.next()){//createavariabletoholdtheappointmentAppointmentTypeappointment=newAppointmentType();//getthenextappointmentfromtheresultssetappointment.time=result.getInt("TIME");appointment.reason=result.getString();appointmentVector.addElement(appointment);}}catch(SQLExceptione){System.out.println("Error:"+e.toString());}}publicvoidinitNetwork(){//loadthedatabasedriverClass.forName("sun.jdbc.odbc.JdbcOdbcDriver");//createtheURLrepresentationofourdatabaseStringurl="jdbc:odbc:Schedule";//maketheconnectiontothedatabasedbConnection=DriverManager.getConnection(url,"username""password");}publicvoidshutdownNetwork(){}} NoticehowthecurrentinvocationstepsthroughtheResultSetandmakesitintoaVector.WhenyourapplicationsneedtohandlemorecomplexresultsfromanSQLquery,youwillneedtodomuchofthesame.InvokingSQLtoMakeaChangeNowwemustimplementtheJavasidetooursetAppointmentoperation.OursetAppointmentqueryassignsanewentryintothedatabase.publicvoidscheduleAppointment(Stringreason,inttime){}WemustfirsttakethereasonandtimevariablesandtranslatethemintoanSQLstatement.Unlikeourpreviousdatabasemodificationexample,herewemustinsertanelement,notsimplychangeanexistingone.Todoso,weneedtousetheSQLInsertstatement.INSERTINTOScheduleVALUES(1,'Meetwithmarketing');WewillonceagainusethePreparedStatementobjecttoputtogetherastatement.publicvoidscheduleAppointment(Stringreason,inttime){try{StatementinsertStatement=dbConnection.createStatement();Stringinsert="INSERTINTOSCHEDULE"+"VALUES('"+appointmentTime+"','"+appointmentReason+"')";insertStatement.executeUpdate(insert);}ShuttingDowntheConnectionInJDBC,wemustclosetheconnectiontoourdatabase.Thisensuresthatthedatabasemanagementsystemhassufficientconnectionsforotherapplicationstoconnecttoit.Forhigh-availabilitydatabases,thisisquiteanimportantcharacteristic.Thedatabasemustbeavailableatalltimes,andeventhoughourconnectiondisappearswhentheapplicationshutsdown,wemuststillpublishaninterfacetothedatabaseconnectionthatwillallowustoeliminateit. publicvoidshutdownNetwork(){}SummaryDatabasesarestoragemechanismsdesignedtoenableyoutowarehousevastquantitiesofdata.BylinkingJavaapplicationstothem,youcancreateprogramsthatareinstantlyuseful.Today,therearehundredsofapplicationsthatinterfacewithdatabasesusingoutdated,archaicapplications.InthenexttwochapterswewillexplorecombiningJava,JDBC,andnetworkobjecttechnologytodevelopenterpriseclassapplications.Chapter5.JavaRMI:RemoteMethodInvocation•DistributedObjects•Client•Server•Callbacks•AJavaRMIVersionoftheFeaturedApp•NewinJDK1.2Aswewereallgrowingup,therewasalwaysaperson(afriend,afoe,oraparent)whoknewjusthowtopushour"buttons"togetadesiredreactionoutofus,sometimesgoodandsometimesbad.Theactionsweweremanipulatedintodoingwerethingsthatwerebuiltintoourpersonalities.Thisideaofpushingsomeoneelse'sbuttonsisexactlytheideabehindRemoteMethodInvocation.Thinkofyourselfasanaction/reactionserverandthethingsyoucouldbemanipulatedintoasyourmethods;nowthinkofyourantagonistasaclienttoyourserver.Iftheclientsendstherightmessages,itcangettheservertodoanythingthatisintheserver'ssetofknownactions.JavaRemoteMethodInvocationisasimple,yetpowerful,Java-basedframeworkfordistributedobjectdesign.Althoughitsharesmanytraitswithitscousin,JavaIDL(Chapter6),ithasdistinctadvantagesoverIDLinseveralkeyareas,notablyusability.JavaRMI-basedobjectscanbequicklydeployedandmanagedacrossnetworks.Ithasseveralshortcomingsthatwewilldiscusslater,butJavaRMIisafastandadequateintroductiontoDistributedObjectProgramming.Inthischapter,wewilldiscussthearchitecturaldecisionsbehindRMIandwhytheyweremade.Wewillalsoguideyouthroughtheprocessrequiredtocreateasimpleclient/serversystemusingtheRemoteMethodInvocationmechanisms.DistributedObjectsRemoteMethodInvocation(RMI)issimilartootherdistributedobjecttechnologies;it,however,enablesyoutocreateapplicationsthatcommunicatewithoneanotherwithouttheoverheadofCORBA.AremotemethodinvocationissimilartoRemoteProcedureCall(RPC)usedfrequentlyinC/C++.Insteadofcreatingandinstantiating anobjectonyourlocalmachine,youcreateitonanothermachineandcommunicatewiththatobjectthroughitsinterface,justasifitwerealocalobject.Thisgivestheeffectofcreatingalocalobjectthatwethentakeholdofwithbothhandsandstretchoutacrossthenetwork.Wethendroponeendononehost(client)andtheotherendonanotherhost(server);thetwoendsarestillconnectedandmakeupasingleobject.Evenifwereplicatetheclientpartoftheobjectonmultiplehosts,westillhaveonlyoneobject.So,withtheadvantagesoftheJavalanguage,youwillbeabletocreatedistributedobjectsthatcommunicatewithoneanother.UnlikeCORBA,yourapplicationsmustbewritteninJava,butthatmaynotbeabadthingintheend.Itwillbedifficulttore-implementyourlegacyapplicationsbecausetheymustberewritteninJava.Yet,beingabletowritedistributedapplicationswithoutexpendinganyrealeffortishighlyattractive.IfJavaisyourlanguageofchoice,thenRMImaybeyourbestcommunicationalternative.WhatIsRMI?Inthegoodolddaysofprogramming,allthethingsyouwantedtodoresidedinoneprogram.Ifyouneededafile,yousimplyopenedit.Ifyouneededtooptimizeyourprogram,youeitherreducedfunctionalityorspeditup.Lately,thenotionofdistributedprogramminghastakentheindustrybystorm.Insteadofopeningafile,youopenanotherapplication.Insteadofreducingfunctionality,youfarmouttheworktoanotherapplicationandkeeptabsontheprocessbycommunicatingwithit.Figure5-1illustratesthedifferencesbetweenlocalandremoteobjectinvocation.Figure5-1.Invocationsonremoteobjectsappearthesameasinvocationsonlocalobjects.JavaRMIenablesyoutofarmoutworktootherJavaobjectsresidinginotherprocesses,orinothermachinesaltogether.Notonlycanyouexecutestepsinparallelusingthreads,butyoucanalsofarmoutworktootherprocessesthatwillexecutestepsinparallelonadifferentmachine! Sure,manyofthealternativespresentedinthisbookenableyoutodothesamething,butwhywouldyouwanttodoallthatworkwhenyoucanletJava—thesamelanguageyou'vespentsomuchfreetimelearninganyway—doalltheworkautomatically?WhereCORBAflauntsitslanguageindependence,RMImakesnoefforttohidethefactthatyouarelockedintoaJava-onlysolution.HowDoesRMIWork?Whenyourclientinvokesyourserver,severallayersoftheRMIsystemcomeintoplay.Thefirst,andmostimportanttotheprogrammer,isthestub/skeletonlayer.ThestubsareJavacodethatyoufillinsothatyoucancommunicatewiththeotherlayers.Forexample,inChapter6,"JavaIDL:InterfaceDefinitionLanguage,"youwillseehowtheIDLtoJavacompilergeneratescodethatwewilllaterfillinanduseastheframeworkforadistributedapplication.Likewise,theJavaRMIsystemautomaticallyenablesyoutouseseveralhelperfunctions.ByinheritingfromtheRMIclasses,yourclassimplementsthestubsorskeletons.Toputitsimply,stubsarereservedforclientcodethatyoufillin,andskeletonsrefertoservercode.Oncethestubsandskeletonlayersarecompleted,theypassthroughtheothertwolayersintheRMIsystem.Thefirstoftheselayersistheremotereferencelayer.Theremotereferencelayerisresponsiblefordeterminingthenatureoftheobject.Doesitresideonasinglemachineoracrossanetwork?Istheremoteobjectthekindofobjectthatwillbeinstantiatedandstartedautomatically,orisitthekindofobjectthatmustbedeclaredandinitializedbeforehand?Theremotereferencelayerhandlesallthesesituations,andmanymore,withoutyourintervention.Finally,thetransportlayerissimilartoatranslatorthattakesyourRMIcode,turnsitintoTCP/IP(orwhatevercommunicationmechanismisused),andletsitflyoverthenetworktotheotherend.BecausetheRMIsystemsupportsatechniquecalledobjectserialization,anyobjectspassedasparameterstoaremotemethod,nomatterhowcomplicated,areconvertedintosimplestreamsofcharactersthataretheneasilyreconvertedintotheiroriginalobjectrepresentation.Therealimplicationofthisisthatonlyobjectsthatareserializablecanbepassedasarguments.Thiscanposeproblemsattimes;forexample,attimesitwouldbeconvenienttopassastreamtoaserverobject,butstreamsarenotserializable,sowecan't.AsyoucanseeinFigure5-2,aclientthatinvokesaremoteserverfirsttalkstoitsstubcode,which,inturn,sendsthemessagetotheremotereferencelayer,whichthenpassesitthroughthetransportmechanismtotheothermachine.Theothermachinetakeswhatitgetsthroughthetransportlayerandretranslatesitintotheremotereferencelayerrepresentation,whichpassesitontotheskeletoncodewheretherequestfinallymakesitsappearanceattheremotemethod.Figure5-2.JavaRMIarchitecture. Stub/SkeletonLayerWhenyourclientbeginstoinvokeaserveronaremotemachine,theAPIwithwhichyou,asprogrammer,areconcernedisthestub/skeletoncode.ByinheritingfromtheappropriateRMIclass,yourobjectobtainsseveralRMImethodsthatyouarerequiredtofillin.Whentheinvocationisactuallymade,theremoteobject(dependingonhowtheserverhasbeendesigned)couldbeareplicatedobject.Areplicatedobjectisanobjectthathasseveralinstancesexecutingatthesametime(possiblycreatedbyafactoryprocess).Forexample,agivenapplicationmayhaveseveralinstancesoftheJavaStringclasswithinitsthreadsofexecution.IftheStringclasswerearemoteserverobject,aclientthatinvokesitshouldnothavetoworryaboutitsvariousinstances.Thestub/skeletonlayerprecludesthisnotionofreplicatedobjects.Whenyouwriteyourapplicationandcode,thenecessarytoolstotalktoaremoteobject,youneednotconcernyourselfwiththeimplementationsontheremoteside.Thestub/skeletonlayeralsoabstractsyoufromthevarioustransportmechanismsintheotherlayers.Inshort,thestubandskeletonlayersbothmakesurethatyourprogramisplatform-independent.RemoteReferenceLayerThereferencelayerservestwopurposes.First,ithandlesthetranslationfromthestubandskeletonlayersintonativetransportcallsonthehostingarchitecture.TheearlyversionofRMIwasnotasplatform-independentasitpurportedtobe.TheproblemlayintheJavaDeveloper'sKit,andnotintheRMIsystemitself.WiththeintroductionofthenextmajorrevisionoftheJDK,theRMIsystemnowfunctionsproperly.TheRMIsystemistrulyplatform-independentasit,andtheJavalanguage,weremeanttobe.Thereferencelayeralsoisinchargeofcarryingoutremotereferenceprotocols.Theseprotocolsmaybepoint-to-pointcommunication(i.e.,localobjecttoremoteobjectinvocations).Or,thereferenceprotocolmayrefertoreplicatedobjects.TheRMI systemensuresthat,whenyouinvokearemoteobjectthathappenstobereplicated,allthereplicatedinstanceswillhearthesamemessage.Thereplicationstrategyiscustomizable,butwereferyoutotheRMISystemArchitecturesectionoftheRMIspecification.Thereisacorrespondingserver-sidereferencelayerthatacceptstheclient-sideinstructionsandretranslatesthemintoprogrammercode.Itensuresthattheinvocationsaremadereliably,andthattheRMIsystemknowsaboutanyexceptions.Exceptionsarethrownfromthislevelforanyproblemsinestablishingconnections,fulfillinginvocationrequests,orclosingconnections.Basically,thereferencelayerisresponsibleforbridgingthegapbetweenprogrammercodeandnetworkcommunication.Itisago-betweenofdata,takingwhatyouwanttodo,andmakingsureitcanbedoneusingthenetwork.TransportLayerWhenthefirstminersfoundgoldinCalifornia,theyexclaimed"Eureka!"Well,Eureka!Thisiswheretheactionis.Eventhoughyouarenotabletomanipulatetheseroutinesyourself,itisimportanttounderstandhowthetransportisimplemented.Fromhere,youwillunderstandthelimitationsofRMIandbeabletomakeanarchitecturaldecisionbasedonthem.Thetransportlayerisresponsibleforsettingupconnections,maintainingthem,alertingapplicationsofproblems,listeningforconnections,andshuttingthemdown.Thetransportlayerconsistsoffourcomponents:theobjects,thespacebetweenlocalandremoteaddressspaces,thephysicalsocket,andthetransportprotocol.Figure5-3illustratesasimpletransportmodel.Figure5-3.Thetransportlayerisresponsibleforallconnections-relatedfunctions.Theobjects,orendpoints,arethebeginningandendofaninvocation.Betweenoneobject'stransportendpointtoanother'stransportendpointresidestheentirecommunicationmechanismonwhichRMIisbased.Thechannelbetweentheaddressspacesisinchargeofupholdingtheconnectionandmonitoringforsignsoftrouble,saythelossofanobjectormaybethelossofthephysicalconnectionitself.ThesocketconnectionisbasicallythesamekindofsocketwesawinChapter3.Aswementionedbefore,socketsreallyarethebasisforallcommunicationsinJava.Finally,thetransportprotocolisthelanguageinwhichsocketstalktooneanother.Localvs.RemoteObjects So,whatarethesemanticdifferencesbetweenlocalandremoteobjects?Allalongwehavestressedthatattheheartoftheentiresystemisthenotionthattotheclientprogrammer,everythinglooksexactlylikenormal,nonremoteJavacode.Infact,evenJavaIDL'sclientapplicationslooknodifferentthanlocalJavacode.JavaRemoteMethodInvocationisquiteinterestinginasemanticsense.Indeed,theveryideathatinstantiatinganobjectthathappenstobeonanothernetworkisinterestinginandofitself,buttoaddtothatthecaveatthattheremoteobjectexhibitsallthepropertiesofalocalJavaobjectaddsacertainamountofusefulnesstothewholematter.WhatkindsofcharacteristicsdoJavaobjectsexhibit?Well,mostimportantly,theyareeasytoimplement.Theyaregarbage-collected,meaningthatonceyourprogramhasnouseforthem,theyareautomaticallydereferencedandtheirresourcesreturnedtothesystem.Wediscussremotegarbagecollectioninthenextsection.Javaobjectsare,ofcourse,platform-independent,asareJavaRMIobjects.Whenyoumakearemotemethodinvocationinanon-Javalanguage,chancesareyoumustlearnnotonlythenuancesofthecommunicationmechanismofyourownmachinebutthatofthemachineyouaretalkingtoaswell.ImaginebeingaSolarisprogrammerwhoistryingtotalktoaWindows95machine!It'shardenoughtomasterSolarisinterprocesscommunicationwithouthavingtolearntheesotericWindows95communicationlayersaswell!JavaRMIfreesyoufromthatmorass,justasJavafreesyoufromrecompilingyourcodeformultiplearchitectures.WhenyouinvokeaRMImethodacrossdifferentplatforms,theRMIsystemadjustsitscommunicationlayersautomatically;andbecausethoselayersareabstractedfromyou,theprogrammer,youneverhavetoconcernyourselfwiththatconfusingnetworkcode.GarbageCollectionOneofthebiggestadvantagestoJavaisthattherearenopointers.Thereisnomemorytodeallocate,andyouneverhavetodealwithmemorystorageschemes.Java'splatformindependencemantrawouldn'tallowitanyway,butifyouweretodevelopformultipleplatforms,youwouldneedtobeconcernedwiththenuancesofmemorymanagementforeacharchitecture,which,likemasteringmultipletransportlayers,isadauntingtask.JavaRMIisnoexceptiontotherule.Infact,itcontainsacomplicatedgarbagecollectionschemebasedonModula-3'sNetworkObjectsconceptofobjectreferencecounters.RMIplacesanobjectreferencecounterintoeachobject.Everytimeanotherobjecttalkstotheremoteobject,theobjectreferencecounterisincremented,andoncetheobjectnolongerneedstheremoteobject,thecounterdecrements.Therearemanyprotectivelayersaroundthegarbagecollectionalgorithmthatpreventprematureobjectdeallocation.MostofRMI'sdistributedgarbagecollectionfarmsofftheworktothelocalJavaVirtualMachine'sgarbagecollectionalgorithm.Thus,RMIdoesnotreinventthewheel,sotospeak. Forexample,whenourlocalobjectbeginsaconversationwitharemoteobject,webegintotalkthroughtheRMIsystem'slayers.Aspartoftheremotereferencelayer,ourlocalobjectcreatesa"network"object.Ontheotherend,attheremotemachine,theremotereferencelayercreatesanothernetworkobjectthatconverseswiththeremoteobject.Theremotevirtualmachinerealizesthattheremoteobjectshouldnotbedeallocatedandholdsoffgarbagecollectionaslongastheremotenetworkobjectisreferringtoit(seeFigure5-4).Thus,theremoteobjectisnotblownaway.Figure5-4.ThecreationofnetworkobjectsduringobjectcommunicationpreventsJava'sgarbagecollectionfrominterruptingtheconversation.Backatthelocalmachine,whenwearenolongerusingtheremoteobject,theremotereferencelayerremovesallreferencestothelocalnetworkobject.OncethelocalJavaVirtualMachinerealizesthatthelocalnetworkobjectisnolongerused,itgarbage-collectsit.Aspartofitsfinalizeroutine,thelocalnetworkobjectsendsamessagetotheremotenetworkobjectthroughthereferencelayerthatitshouldletgoofitsreferencetotheremoteobject.Insodoing,theremotenetworkobjectcausestheremoteJavaVirtualMachinetogarbage-collecttheremoteobject.SecurityWhenyouinstantiatealocalobjectfromwithinaJavaapplet,securityisnotaconcern.Theappletsecuritymechanismhasalreadyclearedyourapplet,andyouarefreetoallocateanddeallocateyourobjects.However,securityisverymuchaconcernforremoteobjects.Whenyoutrytoinstantiatearemoteobject,youmusthavepermissiontodoso.TheAppletclassloaderthatisinchargeofgettingeveryclassyourapplicationrequiresmayormaynotbeabletoinstantiatetheremoteobject.Asaresult,RMIinappletsislimitedtoinvokingmethodsonclassesthatarealreadyinexistence.Youarenotallowedtocreatearemoteobjectbecausetheappletclassloaderwillnotletyou. Appletvs.ApplicationCurrently,RMIserversmustbecreatedasJavaapplications.ServerscannotbeembeddedwithinaWebpage.Thereareseveralreasonswhy,mostnotablythattheappletsecuritymechanismspreventit;but,forthetimebeing,theRMIsystemdoesnotsupportappletservers.WewilldiscussthecallbackalternativeasimplementedinRMIinafewsections.DynamicMethodInvocationsRMIenablesyoutoinvokeaserverwithoutknowinganythingaboutwhatmethodsarecontainedwithintheserver.It'slikegoingintoarestaurantandorderingwithouteverseeingthemenu.Ifyouknowyou'reinanItalianrestaurant,chancesareprettygoodthattheyofferspaghettiandmeatballs.Likewise,ifyouknowwhatkindofserveryouaretalkingto,youcaninvokeitwithoutactuallyknowinganythingaboutthemethodsitimplements.OverviewofRMIJava'sRemoteMethodInvocationsystemisasignificantlyeasierandlighterweightapproachtodistributedobjectsthanJavaIDL.ContainedcompletelywithintheJavalanguage,RMIisanextensiontothelanguageitself,whereasJavaIDLisalanguage-independentJavaimplementation.RMIissimple,fast,andeffectiveforlightweightdistributedsystems.Asyourapplicationsbecomemorecomplex,JavaIDLmaybeyourbestalternative.Nevertheless,clientandserverprogrammingisquitesimplewithRMI.Aswewillseeinthenexttwosections,creatingclientsinRMIisanaturalextensiontocreatingJavaobjects.ClientInordertocreateadistributedsystem,onepartofyourobjectsmustbeaclient,andtheothermustbeaserver.Sometimesserverscanbeclientsaswell,butinthissectionwewilldiscussthesimplestcase.RMIwasdesignedwiththeideathat,withminimaleffort,youwillbeabletocreatecomplexdistributedsystemswithalltheadvantagesofJavaandnoneofthedetrimentsofotherdistributeddesigns.Infact,withtheadditionofasinglelineinyourcode,youcanmakeanobjectadistributedobjectinsteadofalocalone.ThebeautyofRMIisthateventhoughyourcodegivestheillusionofnormal,single-processapplications,itisinfactadistributedsystem.Whenyougetoverloadedatwork,youbegintodelegatetoothers.Likewise,JavaRMIsaysratherthanoverloadinganapplication,whynotdelegatetootherapplications?RMIClientMethodologyLet'ssayyoucallupPenney'sanddecidetoorderoneofthosefancytoastercoversfromtheircatalogforyourmother'sbirthday.Theoperatorgreetsyouandasksforyourordernumber.Becausetheclientisalwaysright,youdecidetoamuseyourself andannoythepoorpersontakingyourorder.Insteadofbeingcooperativeandactuallyhavinganordernumber,yousimplytellhimthatyouwantthe"toasterovencoverwiththepurplepolkadotsandaportraitofHeathShulerontheside."Clearlyamused,theoperatorgoestohiscatalogdatabaseandasksforthe"toasterovencover"withtheappropriatedescription.Whathegetsinreturnistheordernumberandsoheisabletoprocessyourorder.Similarly,inRMIyouhavetogotoacatalogofobjectsandaskfortheobjectbyitscommonlyknownname.Onceyouhavetheobjectyoucancontinuetoprocessyourapplication.Thestepsyouneedtotakeinordertocreateaclientare:1.GettheclientobjectfromtheNamingService.2.Processtheobjectandreadyitforinvocation.3.Invoketheobject.RMIRemoteClassesRMI'sRemoteclassisastandardinterfacethatyoumustextendfromyourserverinordertoexportfunctionalitytoanRMIclient.AllremoteobjectsinheritfromtheRemoteclass,andyourclientneedstoknowwhatit'stalkingto.It'skindoflikeknowingthelanguageyouaregoingtotalkbeforeyouconversewithsomeonefromanothercountry.Onceyourserverinheritstheremoteobject,itcanbeinstantiateduponandinvokedonbyremoteobjects.Intheexampleinthissection,weareimplementingasimpleRMIclientthatwillmakeremotemethodinvocationstoanRMIservertoretrievestatisticaldataforagivenNFLteam.TheStatsServerimplementsthreefunctionsthatwewillimplementinourRMIserverssection.Wewantourclientstobeabletogetthetotalrunningyardage,thetotalpassingyardage,andthetotalnumberofturnoversforateamthatwespecifybyastring.WestartbyincludingRMIinourfile,anddefiningtheclientclassitself.packagermi.Stats1;publicclassStatsClient{}TheRemoteclassesalsoimplementremoteversionsofthestandardJavaexceptions.InheritingfromJava'sexceptionmechanism,RemoteExceptionscandoeverythingthatJavaexceptionscando.TheonlydifferencebetweenthetwoisthatremoteexceptionsrefertoproblemswithremoteobjectsratherthanlocalJavaerrors.TIPTheRemoteObjectclassextendstheJavaObjectclass.So,ifyouweretocreatetwoversionsofanapplication—onethattalkstoremoteobjectsandonethatrefersonlytolocalones—itwouldsimplybeamatterofchangingtheinheritance. RMI'sNamingSystemAswediscussedearlier,theRMIsystemprovidesasimplenamingsystemthatallowsyoutorefertoobjectsasspecialkindsofstrings,ratherthanasspecialwords.Inordertousearemoteobject,youmustfirstretrieveitfromtheRegistry.TheRegistryensuresthatanobjectisavailableforuse.Itbindstheobjectreferencetoasimplestringandprovidesroutinesforaccessinganobjectbythestringunderwhichitisstored.InordertousetheRegistry,youmustfirststartituponsomemachineonyournetwork;forourpurposesthiswillbeyourlocalmachine.TheRegistryclingstoapredefinedport(becauseitisnotawell-knownportandthestubsandskeletonshidealltheprotocolfromyou,youdon'tneedtoknow;butifyou'rereallycuriousitis1099)onyourmachineandfunnelsTCP/IPmessagesbetweenclients,servers,andtheRegistryonthatport.EmbeddedwithinthecodefortheRMIsystemisthisspeciallyassignedport,enablingtheRMIsystemtoalwaysbeabletoaccessarunningRegistry.TheRegistryisastand-aloneJavaapplication,sostartingitisprettysimple:%prompt%rmiregistry&(onUNIXsystems)D:startrmiregistry(onWindowssystems(95,98orNT))Tostartuptheregistryonsomeportotherthanthedefault,simplyfollowthecommandwiththedesiredport.D:startrmiregistry12345GettinganobjectfromtheRegistryisactuallyprettysimple.YoucangetanobjectandbegininvocationsonitimmediatelybyinvokingoneoftheRegistry'sthreefunctionsforbindingobjectstostrings,unbindingobjects,andretrievingobjects:packagejava.rmi;publicclassStatsClient{StatsClient(){//gettheremoteobjectfromtheRegistryStringurl="//localhost/STATS-SERVER";StatsServerremoteObject=(StatsServer)Naming.lookup(url);}} RemoteInvocationsTheobjectthatisretrievedisaremotebaseobject.WeneedtotransformthatgenericremoteobjectintoaspecificStatsServerobject.Ingeektermsthisisreferredtoasnarrowing.WecannarrowourremotebaseobjectdowntoaStatsServerobjectbyperformingasimplecastoperation,givingusaccesstoallthefunctionswithintheStatsServer:packagejava.rmi;publicclassStatsClient{StatsClient(){//gettheremoteobjectfromtheRegistryRemoteremoteObject=Naming.lookup("STATS-SERVER");//narrowtheobjectdowntoaspecificoneStatsServerstatsServerInterface;if(remoteObjectinstanceofStatsServer)statsServerInterface=(StatsServer)remoteObject}}Finally,wearereadytoinvokemethodsonourremoteserver.Rememberthatwehavethreepossiblefunctionstochoosefrom.Creatingauserinterfacefortheclientisatrivialtaskandshouldbeintegratedintotheapplicationjustasyounormallywould.Here,weinvokeallthreefunctionsandreturnthedatatotheuseronthestandardoutputdevice:packagejava.rmi;publicclassStatsClient{StatsClient(){//gettheremoteobjectfromtheRegistryRemoteremoteObject=Naming.lookup("STATS-SERVER");//narrowtheobjectdowntoaspecificoneStatsServerstatsServerInterface;if(remoteObjectinstanceofStatsServer)statsServerInterface=(StatsServer)remoteObject//maketheinvocationSystem.out.println("Totalyardageis:"+StatsServerInterface.getTotalRunningYardage("Redskins"));}} CatchingExceptionsSofarwehavedonenothinginthewayoferrorchecking.Inorderforourclienttohandleeverypossiblecontingencyduringaremoteinvocation,itneedstocatchanyexceptionsthrownbytheserver.Duringanormalremoteinvocation,theexceptionscanbeanythingfromuser-definedexceptionswithintheservertostandardRMItransportexceptions.Inanyevent,youcancatcheithergenericJavaexceptionsorspecificRMIones.RMIclientinvocationsshouldcatchoneofsevendifferentexceptions.TheRemote-ExceptionclassistheparentclassofallexceptionsthrownbytheRMIsystem.OtherexceptionsincludeRegistry-thrownexceptions,suchasAlreadyBound-ExceptionandNotBoundException.RMIobjectinvocationsthemselvesthrowfourkindsofexceptions:1.StubNotFoundException2.RMISecurityException3.NoSuchObjectException4.UnknownHostExceptionUsingthestandardJavamethodologyforaddingexceptionstoaprogram,wecatchtheRMIexceptionsasfollows:packagejava.rmi;publicclassStatsClient{StatsClient(){//gettheremoteobjectfromtheRegistrytry{RemoteremoteObject=Naming.lookup("STATS-SERVER");}catch(java.rmi.NotBoundExceptionexc){System.out.println("Errorinlookup()"+exc.toString());}//narrowtheobjectdowntoaspecificoneStatsServerstatsServerInterface;if(remoteObjectinstanceofStatsServer)statsServerInterface=(StatsServer)remoteObject//maketheinvocationtry{System.out.println("Totalyardageis:"+statsServerInterface.getTotalRunningYardage("Redskins"));} catch(java.rmi.RemoteExceptionexc){System.out.println("Errorininvocation"+exc.toString());}}}HandlingSecurityConstraintsBecausewedynamicallyloadclassesfromthefilesystemwithinourclient,wemustsetupacorrespondingJavasecuritymanagerwithinourclient.Theclient'ssecuritymanagerpreventstheclientfromabusinganyprivilegesgrantedbytheserver.Forexample,ourservermayhaveunrestrictedaccesstothelocalfilesystem.Inordertokeeptheclienthonestandpreventitfromhavingthesameunrestrictedaccesstotheserver'shost,theclientsecuritymanagermonitorstheloadingprocessoftheremoteclassandsetstheappropriatefileaccesspermissions,asrequiredbytheclient'shostmachine.InourStatsServerexample,ourclientloadstheremoteStatsServerandbeginsinvocationsonit.TheStatsServercouldverywellgetitsdatafromalocalfileordatabase.Inordertodoso,theStatsServerwouldhavepermissiontoreadand/orwritethelocalfileordatabase.Tokeepourclientfromabusingthisright,wesetthesecuritymanagersothattheclientinheritstherestrictionsofitsmachine.Iftheclientwereinabrowser,itwouldinheritthesecurityrestrictionssetinthebrowser.Ifitwereastand-aloneapplication(asisthecaseinthisexample),itwouldbegiventheaccesspermissionsofthestand-aloneapplication.Addingandsettingthesecuritymanagerisasimplematterofinsertingalineintheclient.WewilldiscussRMISecurityManagerinthenextsectionaswedesigntheserverforthisclient.packagejava.rmi;publicclassStatsClientextendsRemote{StatsClient(){//settheclientsecuritymanagertry{System.setSecurityManager(newRMISecurityManager());}catch(java.rmi.RMISecurityExceptionexc){System.out.println("Securityviolation"+exc.toString());}//gettheremoteobjectfromtheRegistrytry{ RemoteremoteObject=Naming.lookup("STATS-SERVER");}catch(java.rmi.NotBoundExceptionexc){System.out.println("Errorinlookup()"+exc.toString());}//narrowtheobjectdowntoaspecificoneStatsServerstatsServerInterface;if(remoteObjectinstanceofStatsServer)statsServerInterface=(StatsServer)remoteObject//maketheinvocationtry{System.out.println("Totalyardageis:"+statsServerInterface.getTotalRunningYardage("Redskins"));}catch(java.rmi.RemoteExceptionexc){System.out.println("Errorininvocation"+exc.toString());}}}ClientOverviewAsyoucansee,designingaclientinRMIisaprettystraightforwardprocess.Oncetheclientisfinished,youmustcreateaservertowhichtointerface.Wewilldosoinamoment,butweshouldkeepinmindthattheclientportionofourclient/serversystemchangesmostoften.Therefore,wehighlyadvisethatyoucreateyourclientswithastrongmodulardesign.Insodoing,youcanbuildsoftwarecomponentsthatareeasilyreplaced.Furthermore,theuserinterfaceaspectsofyourapplicationwillmostlikelyaffecttheclientandshouldnotplayapartinserverdesign.ServerServersenableotherobjectstoconnecttoyourlocalobjectasiftheyactuallyresidedontherequestingmachine.Totheclientnothingisdifferent,buttheserverrequiressomeaddedfunctionalitytosupportTCP/IPprocessingandcommunication.Furthermore,aserverneedstoincludealltheunderlyinggarbagecollectionmechanismsthatenableittobehaveasanormalJavaobjectthatwilldisappearifitisnolongerused.RMIServerClassesInordertogettheJavatoolsnecessarytodevelopanRMIserver,youneedtomakesureyourclassesinheritfromtheRemoteServerclass.TheRMIsystemprovidesseveraldifferentversionsoftheRemoteServerclass,butasofnowRMIgivesyouonlytheUnicastRemoteObjectclass. TheRemoteServerclassextendsRemoteObject,whichgivesyouallthefunctionalityyouhadinaclient.Ifyourserverwilleventuallybeaclientaswell,youneednotinherittheclientcodeagain.Furthermore,theRemoteObjectsuperclassalsomakessurethatyouhaveaccesstotheentireRMIsystem.TheRemoteServerclassextendstheRemoteObjecttoprovideutilityfunctionsgetClientHostandgetClientPort,whichenableclientstodeterminetheproperporttoopeninordertotalktoyourserver.TheextendedclassUnicastRemoteObjectisaformofaRemoteServer.Eventually,JavaRMIwillgiveyouseveraldifferentversionsofcommunication.TheUnicastserverhasthefollowingthreecharacteristics:1.Theservercannotbestartedremotely.Itmustexistalreadyandthereferencelastsonlyforthelifeoftheprocess.2.TCP/IPisusedunderneath.3.Anobjectstreamisusedtopassparametersandinvocationsfromclienttoserver.OnceyourclassinheritsfromUnicastRemoteObject,youcancreateyourserverusingthetwoconstructorsprovidedwiththeclass.Thefirstconstructorforcesyoutocreateanobjectonthedefaultport,andtheotherallowsyoutospecifytheport.CreatingaServerInterfaceRMIisdrivenbythenotionofinterfaces.Asyouwillrecall,interfacesenableyoutoseparatethemethodsignaturesyoupublishtotheworldfromthewaythosemethodsareactuallyimplemented.Forexample,Icantellyouthatyourcomputercomeswithamouse.Youwillknowhowtouseit,howtocleanit,andhowtofeeditcheese.Inotherwords,allmiceshareacommoninterface.IfIwerethentoaddthatyouweregettingalasermouseliketheonessuppliedwithSunSPARCstations,youwouldnothavetomakeahugeshiftinthinkingtousethenewkindofmouse.Youstillknowhowtouseit,howtocleanit,andhowtofeedit.InourStatsServerexample,weneedtocreateasimpleinterfacewiththreedifferentmethodsthatcanbeinvokedonit,likeso:publicinterfaceStatsServerextendsRemote{intgetTotalRunningYardage(StringteamName)throwsRemoteException;intgetTotalPassingYardage(StringteamName)throwsRemoteException;intgetTotalTurnovers(StringteamName)throwsRemoteException;}ImplementingaServerTheinterfacedefinesthecontractthatyoumustnowfulfill.Inorderforyourclient'sinvocationtomapontotheserver'sactualimplementation,youneedtomakesurethat yourserver'smethodssignaturesmatchtheinterfacesignaturesexactly.YourserverimplementationmustimplementtheUnicastRemoteObjectclasswespokeofearlier,aswellasextendtheStatsInterfacewecreated:importjava.rmi.*;publicclassStatsServerImplextendsUnicastRemoteObjectimplementsStatsServer{}Firstweneedtoimplementtheconstructorfortheserver.Becausetheserverwillbeastand-aloneapplication(RMIdoesnotyetsupportappletclientsorservers),weneedtomakesurethatallourinitializationisdoneinthatconstructor.RMIrequiresaconstructortobepresent.InorderfortheRMIsystemtocompleteitsowninitialization,theconstructormustbeinvokedandmustthrowaRemote-Exceptionincasesomethinggoeswrong.Ourconstructorshouldalsocallthesuperclass'sconstructor:importjava.rmi.*;publicclassStatsServerImplextendsUnicastRemoteObjectimplementsStatsServer{StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}}Nowyouneedtoimplementthethreemethodswehaddefinedinterfacesfor:importjava.rmi.*;publicclassStatsServerextendsUnicastRemoteObjectimplementsStatsInterface{StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}publicintgetTotalRunningYardage(StringteamName)throwsRemoteException{ if(teamName.equals("Redskins"))return432;elsereturn129;}//weimplementtheothersasabove…}Asyoucreateinterfacesandmethods,keepinmindthatthemethodsthemselvesneednotbeconcernedthattheyresideinanRMIserver.Infact,theobjectsyoucreateasRMIserversshouldbeinlinewiththeRMIphilosophy.Theseareobjectsthatcouldjustaseasilybelocalobjects.Thefactthattheyareremoteshouldnotaffecttheactualimplementationofthemethodsthemselves.RMIRegistryClassesAsyoucansee,creatinganRMIserverisjustaseasyascreatingaJavaobject.Wedefineourinterface,implementtheinterface,andnowweneedtopublishtheinterfacetotheworldsothatanyclientcanaccessanduseourStatsServer.Aswementionedearlier,theRMIRegistrykeepstrackofobjectsusingasimplestring.InourclientweretrievedanobjectbythenameofSTATS-SERVER.Inorderforthisservertoberetrievedinthatinstance,weneedtousethesamestringhereaswell.Typically,RMIRegistryproceduresareimplementedinthemainroutineofyourstand-aloneapplication.Inthefuture,whenRMIsupportsappletsaswell,theseprocedureswillbeplacedintheinitmethod:importjava.rmi.*;publicclassStatsServerextendsUnicastRemoteObjectimplementsStatsInterface{StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}publicintgetTotalRunningYardage(StringteamName)throwsRemoteException{if(teamName.equals("Redskins")return432;elsereturn129;}...weimplementtheothersasabove...publicstaticvoidmain(Stringargs[]){//createalocalinstanceofourobject StatsServerImplstatsServer=newStatsServerImpl();//putthelocalinstanceintotheRegistryNaming.rebind("STATS-SERVER",statsServer);}}RMIServerSecurityConstraintsAswediscussedwhenwedesignedtheclientforthisobject,weneedtospecifyasecuritymanager.ThemanagerweimplementedintheclientistheJavaRMI-SecurityManager.NOTETheRMISecurityManagershouldbeusedwhentheserverrequiresminimalsecurityrestrictions.Ifyourequireasecuritysystemtoprovidemorerobustaccesscontrol,feelfreetosubstituteyourfavoritesecuritymanagerinitsplace.Inanyevent,thesecuritymanagershouldbesetwiththeSystemclass'ssetSecurityManagermethod.Ifyoudonotspecifyasecuritymanager,thentheRMIsystemloadsonlythoseclassesspecifiedintheJavaCLASSPATHenvironmentvariable.CAUTIONRMIusestheCLASSPATHasadefaultsecuritymanagertopreventunexpectedandpotentiallydangerousresultsfromRMIobjects.Addingasecuritymanagerisassimpleasitwaswiththeclient.Rememberthattheclient'ssecuritymanagerpreventsdownloadedobjectsfrommodifyingthelocalfilesystem.Theserver'ssecuritymanagerpreventstheserverfromdoingharmtothehostmachine.Thiskindofcontrolisnotnecessarilymeanttocontroltheserveritself,buttopreventanyclientfromusingtheserverinamaliciousmanner.importjava.rmi.*;publicclassStatsServerImplextendsUnicastRemoteObjectimplementsStatsServer{StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}publicintgetTotalRunningYardage(StringteamName) throwsRemoteException{if(teamName.equals("Redskins")return432;elsereturn129;}...weimplementtheothersasabove...publicstaticvoidmain(Stringargs[]){//setthesecuritymanagertry{System.setSecurityManager(newRMISecurityManager());//createalocalinstanceofourobjectStatsServerImplstatsServer=newStatsServerImpl();//putthelocalinstanceintotheRegistryNaming.rebind("STATS-SERVER",statsServer);}catch(java.net.MalformedURLExceptionme){System.out.println("MalformedURL:"+me.toString());}catch(RemoteExceptionre){System.out.println("RemoteException:"+re.toString());}}}GeneratingStubsandSkeletonsOncetheinterfaceiscompleted,youneedtogeneratestubsandskeletoncode.Stubsaresortoflikebackupquarterbacks.Theystandinforthestarterwhenheisnotavailable.SometimestheactualJavaobjectcouldresideinanothervirtualmachine.Stubcodeisgeneratedtostandinfortheremoteclassthatcannotbeaccessedinordertoprovideasuccessfulcompile.TheRMIsystemprovidesanRMIcompiler(rmic)thattakesyourgeneratedinterfaceclassandproducesstubcodeonitsbehalf:%prompt%javacStatsInterface.java%prompt%javacStatsServer.java%prompt%rmicStatsServer Oncethestubcodeiscompiledandlinkedin,yourRMIapplicationmaybecompletedandinstalledintheRegistry.OncetheRMIapplicationresidesintheRegistry,itisavailablefortheclienttoinvokeaswedidintheprevioussection.Oncethestubsandskeletonsarecompleted,youmuststarttheRMIRegistrybyhand.RMIobjectsarenotstartedautomaticallyuponinvocation.Therefore,becausetheRMIRegistryisanRMIobjectinitsownright,itmustbestartedbyhand:D:startrmiregistryOncetheRegistryisstarted,theservercanbestartedandwillbeabletostoreitselfintheRegistry.IftheserverisavailablethroughtheRegistry,theclientcaninvokeit.D:java-Djava.security.policy=C:advjavacdrmiStats1policy.allrmi.Stats1.StatsServerThisalllooksrathercomplicated,solet'stakeitapartandlookatwhatwearesaying:JavaWeareaskingtheJavavirtualmachinetorunsomething.-DSetasystempropertytosomevalue.Inthiscasesetjava.security.policytowhateverisinthefileC:advjavacdrmiStats1policy.all(becauseofthefinergrainedsecuritymodelinJava2.0youmustsetupasecuritypolicyforRMI).rmi.Stats1.StatsServerImplSincewecreatedourclientandserverinapackageandmyclasspathissettoC:advjavacd,wemustfullyqualifytheclasswewanttorun.Needlesstosay,ifyouputtheadvjavacdrmistats1directoryinyourclasspathandstartedtheserverupfromthatdirectory,thiscouldbereducedtoD:java-Djava.security.policy=policy.allrmi.Stats1.StatsServerImplBecausethisisalittlelengthyandcomplicated,itisbesttoputitinascriptorbatfile(seetheR.BATfileinthermistats1directoryontheaccompanyingCD).LateronwhenwecompareJavaIDLandJavaRMI,wewilldiscoverthatlocationindependenceandautomaticstartuparevitaltomission-criticalapplications.Fornow,takenoteofthedifferencesasyouformulatethealternativemoresuitedforyourapplications.NOTEAsyoucansee,creatinganRMIserverisnotadifficulttask.Infact,itisamazinglysimilartoJavaIDLinmanyrespects.Thisisnotanaccident.BothJavaIDLandJavaRMIsharethesamelineagewithinSunMicrosystems.The architectsofRMIandthebrainsbehindJavaIDLbothcomefromthesamedistributedobjectprojects.AsaresulttheyhavecreatedJava-baseddistributedobjectsystemsthatsharethesamecharacteristics.ServerOverviewSonowthatwecancreateserversinRMI,wecanpublishservicestotherestoftheworld.Clientsanywherecanuseourserversasiftheywereremoteobjects.But,whatifwewantedeveryclienttouseadifferentinstanceoftheremoteserver?Ifweusedourcurrentparadigm,wewouldhavetomakesureourclientscreatedtheirownserversomewhereelse.But,wewantthemtoallusethesameserverprocessremotely,justusedifferentinstancesoftheserveritself.Wecanaccomplishthiswiththenotionoffactories.Factoriesenableclientstocreateserversonthefly,allofthemcontainedwithinthefactory'sprocess.Thatway,iftwoclientsarebangingonthesamekindofserver,whatonedoeswon'taffecttheexecutionoftheother.CallbacksWhenwelastspokeofcallbacks,weusedthemasameanstogetaroundthelimitationofhavingnoserverswithinanapplet.ItenabledustocreateamethodthatwouldallowaC++objecttoinvokeourJavaappletembeddedinsideaWebpage.WhilewesacrificedbynothavingcontrolovertheinitializationorstartupofthecallbackappletaswewouldhavehadwithaCORBAserver,weweresatisfiedthatourappletwouldbeabletoactastherecipientofdata.JavaRMIhassimilarlimitationswithitsservers.Unfortunately,aJavaRMIservercannotbeembeddedwithinaWebpage,sowehavetoimplementsimilarcallbackmechanismsinsideourserversandclients.WhyCallbacks?Let'ssaythatclientsofourStatsServerswantedtodisplaynewdataasitarrivedtotheserver.Ratherthanroutinelypingingtheserverforinformationandcreatinganetworkbacklog,wewouldlikeourclienttochangeitson-screenstateinformationonlywhentheserverhasnewinformationtoreport.JustasweusedthecallbackmechanisminJavaIDLtosupportthiskindofdynamicupdate,wewillimplementaserver-driveneventmechanismthatwillenableourclienttopassivelyupdateliveinformation.Oursolutionshouldbescalable,meaningthatitshouldworkjustasefficientlyforafewclientsasitshouldforseveralthousandclients.Itshouldbeeasytoimplement,anditshouldsolvetheproblemwithouthassletotheclientprogrammer.CreatingtheCallbackBecauseourcallbackobjectessentiallywillbeanRMIobject,weneedtocreateanewclientinterface.Asyoucanseeinthefollowingcode,weneedtocreateamethodthattheserverwillinvokewhenitsensesachangeinitsinformation. Inordertosetupthisclientinterface,wemustcreateanewpublicinterfacefilesimilartotheoneswecreatedfortheStatsServeritself:publicinterfaceStatsCallbackInterface{voidstatsChanged(StringteamName,intpassingYards,intrushingYards,intturnovers);}WealsomustmodifytheStatsServeritselfsothatitcanregisterforthesecallbacks.Rememberthatweneedtotelltheserverthatithastosendusinformationbackwhenitgetsachange.Inordertodoso,wehavetosenditanobjectonwhichitcaninvokethecallback.BecauseourclientwillimplementtheStatsCallbackInterfaceobject,weshouldpassanobjectofthattypetotheregistrationfunction://newfile...publicinterfaceStatsServerInterfaceextendsRemote{intgetTotalRunningYardage(StringteamName);intgetTotalPassingYardage(StringteamName);intgetTotalTurnovers(StringteamName);VoidaddCallback(StatsCallbackInterfacestatsCallbackObject);}ImplementingtheCallbackClientNowthatwehavecreatedtheproperinterfacestoourcallbackclientandchangedtheservertousecallbacks,weneedtomodifytheclientappropriatelysothatitwillregisterforacallbackasthefirststepinitsowninitializationphase.Rememberthat,whenevertheservergetschanged,theclientmakesacalltothestatsChangedfunction,soweneedtoaddthatfunctiontoourclientclass.Inaddition,weneedtomakesurethattheclientimplementstheStatsCallbackInterfaceinterface;otherwise,itwillnotbeabletosenditselftotheserverandberegisteredforanupdate.packagejava.rmi;publicclassStatsClientextendsStatsCallbackInterface{ publicvoidstatsChanged(StringteamName,intpassingYards,intrushingYards,intturnovers){}StatsClient(){...sameasbefore...}}FillingintheCallbackMethodNow,weneedtodosomethingwiththeinformationwereceivewhenacallbackisinvoked.Fornow,we'llwriteourresultstothestandardoutputdevice,butkeepinmindthatwecouldjustaseasilyhaveauserinterfacehandleourdisplayroutines.packagejava.rmi;publicclassStatsClientextendsStatsCallbackInterface{publicvoidstatsChanged(StringteamName,intpassingYards,intrushingYards,intturnovers){System.out.println("Receivedynamicupdate:");System.out.println("Yardspassing:"+passingYards);System.out.println("Yardsrushing:"+rushingYards);System.out.println("Turnovers:"+turnovers);}StatsClient(){...sameasbefore...}}RegisteringCallbacksAfterwe'vecompletedtheCallbackmethoditselfandmodifiedalltheinterfaces,weneedtohavetheclientadditselftotheserver'scallbacklist.Theserverthenwillbe abletogodownthelistwheneveritgetsachangeandinvokethestatsChangedmethodonalloftheclients.However,theserverwillnotbeawareoftheclientunlesstheclientregistersitselfforupdates.packagejava.rmi;publicclassStatsClientextendsRemote{publicvoidstatsChanged(StringteamName,intpassingYards,intrushingYards,intturnovers){System.out.println("Receiveddynamicupdate:");System.out.println("Yardspassing:"+passingYards);System.out.println("Yardsrushing:"+rushingYards);System.out.println("Turnovers:"+turnovers);}StatsClient(){//settheclientsecuritymanagertry{System.setSecurityManager(newRMISecurityManager());}catch(java.rmi.RMISecurityExceptionexc){System.out.println("Securityviolation"+exc.toString());}//gettheremoteobjectfromtheRegistrytry{RemoteremoteObject=Naming.lookup("STATS-SERVER");}catch(java.rmi.NotBoundExceptionexc){System.out.println("Errorinlookup()"+exc.toString());}//narrowtheobjectdowntoaspecificoneStatsServerstatsServerInterface;if(remoteObjectinstanceofStatsServer)statsServerInterface=(StatsServer)remoteObject//registerthecallbackrightheretry{statsServerInterface.addCallback(this);}catch(java.rmi.RemoteExceptionexc){ System.out.println("Errorinlookup()"+exc.toString());}}}TIPNotehowweremovedtheinitialinvocationontheserverfromthepreviouslisting.Withcallbacksadded,wedonothavetogototheservertogetinformation,theserverwillcometoustogiveusinformation.Wouldn'titbeniceiftheBMWdealercametoyoutogiveyouacarinsteadofthewaytheydothingsnow?Wemustnowmodifytheservertoaddthecallbacktoitslist.LikeSantaClaus,itcheckstoseeifeverythingisnaughtyorniceandmakesureyouaresignedupforyourgift,inthiscaseaseriesofupdatestotheserver.Ourserverkeepstrackofeachcallbackobjectinavectorsothatitiseasytotraversethelistwhenthetimecomestoprovideanupdate.importjava.rmi.*;publicclassStatsServerextendsUnicastRemoteObjectimplementsStatsServerInterface{//thelistofcallbackobjectsVectorcallbackObjects;StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}publicvoidaddCallback(StatsCallbackInterfacestatsCallbackObject){//storethecallbackobjectintothevectorcallbackObjects.addElement(statsCallbackObject);}publicintgetTotalRunningYardage(StringteamName){if(teamName.equals("Redskins")return432;elsereturn129;} ...weimplementtheothersasabove...publicstaticvoidmain(Stringargs[]){//setthesecuritymanagertry{System.setSecurityManager(newRMISecurityManager());}catch(java.rmi.RMISecurityExceptionexc){System.out.println("Securityviolation"+exc.toString());}//createalocalinstanceofourobjectStatsServerstatsServer=newStatsServer();//putthelocalinstanceintotheRegistryNaming.rebind("STATS-SERVER",statsServer);}}InvokingCallbacksNotethatourserverinitscurrentstatedoesnothaveanymethodswithwhichitwillacceptchangesintheinformationitsendsback.YourserversmorethanlikelywillincludeamethodorsomethingsimilartosetPassingYards.WehavecreatedafakesetPassingYardsmethod,whichfollows,thatgetstheteamnameandthepassingyardageforthatteamasaparameter.Seehowweactuallyinvokethecallbacksfromwithinthisfunction:importjava.rmi.*;publicclassStatsServerextendsUnicastRemoteObjectimplementsStatsServerInterface{//thelistofcallbackobjectsVectorcallbackObjects;StatsServer()throwsRemoteException{//callthesuperclass'constructorsuper();}publicvoidaddCallback(StatsCallbackInterfacestatsCallbackObject){ //storethecallbackobjectintothevectorcallbackObjects.addElement(statsCallbackObject);}publicvoidsetPassingYards(StringteamName,intpassingYards){//doeverythingthatneedstobedonetosetthevariable//internally...//nowgodownthevectorandinvokeon//eachcallbackobjectfor(intx=0;xallThePhonesInMyHouse;Thus,theprecedingIDLdeclarationsmaptoreasonablystraightforwardJavacounterparts:PhoneallThePhonesInMyHouse[];TheEnumerationandUnionconstructedIDLtypesaremuchmorecomplicated.BecauseJavasupportsneitherenumeratedtypesnorvariableclasses,severallayersofadditionalJavainfrastructuremustbeprovidedtoimplementthedetailsoftheIDLtypesproperly.ExceptionsJavasupportsanexceptioncapabilityverysimilartobothIDLandC++.Asaresult,themappingbetweentheIDLandJavaisextremelyobvious.Furthermore,CORBAC++programmerswillfindthatthehelpermethodsprovidedbyJavaexceptionsaremuchmoreintuitiveandeasiertousethantheirC++counterparts.Intheend,theJavaexceptionandtheIDLexceptionareperfectpartnersinobject-orientederrortracking.JavaandCORBATogetherBecauseCORBAisdesignedasanall-encompassingstandarddesignedtoprovideanswerstomost,ifnotall,object-orientedprogrammingquestions,itdoesnotquitefitintotheJavaphilosophy.JavawasdesignedastheexactantithesistoC++.BothJavaandC++areobject-orientedlanguages;however,Javadoesnotattemptto,nordoesit,satisfyC++andCORBA'sinsatiableneedtobeeverythingtoallpeople.But,foralltheirdifferences,JavaandCORBAcanbemadetoworkwelltogether.Aswehaveseeninthissectionandwewillseeinthenextfewchapters,CORBAprovidesatonoffunctionality.Mostofitwillneverberequiredbytheaverageprogrammer,andthusitcanbecomequiteaburden.Meanwhile,Javaisaccessibletoallprogrammers,bothbeginnerandhighlyexperienced.JavaactuallymakesCORBAmanageablebecauseCORBAprovidestheplumbing,whileJavagivesyou,theprogrammer,ameanstoaccesstheplumbingwithoutknowinghowitworks.Afterall,youdon'tcarehowyourcarworks,youjustcarethatitdoes.Similarly,noone(outsideofgeekswhodesperatelyneedalittlebitofsun)reallycareshowCORBAworks.Onceyouarecomfortablewithlanguagemappings,itistimetomoveontoactuallydevelopingclient/serverapplicationsusingCORBA.WewillusetheIDL,anditscorrespondingJavalanguagemapping,todevelopaclientandserver.CORBAClients WritingaCORBAclientisprettysimple,ifyoucangraspthenuancesofthelanguagemapping.Afteryouobtaintheinterface(usuallybylookingattheIDL)fortheserveryouwishtocontact,youhavetogenerateJavastubs.Javastubscontainalltheunderlyingfunctionalityneededtomakeacallacrossanetworktoaserverinanunknownlocation.Rememberthatyourserverwillnotbeinanydefinitelocation;infact,thebeautyoftheNamingServiceisthatthecorrespondingstringnamecanpointyoutoanyobjectatanytime.Withthatinmind,thelastthingyouwanttoconcernyourselfwithisnetworkcode.LettheORBdealwithallofthat,andyoucanconcentrateoncreatingaclientthatworksforyou.YourclientwillbemostlyaUserInterface.ThefewinstancesinwhichitneedstomakeanetworkcallareusuallytorelayinformationfromtheUIbacktotheserver,andtorefreshinformationontheUIwithdatastoredontheserver.Inclient/serverparlance,thisiscalleda"thinclient,"meaningthatthefunctionalityoftheclientrelatedtotheserverisminimal.DesigningaUserInterfaceSincethebeginningofthe"Javarevolution,"anenormousnumberofGUIbuildershavebeenreleased,allwithcutecoffee-relatednamesthatweredevisedbyamarketerinacoldsweat.Inthissection,weassumethateveryclientisathinclient,choosingtoconcentratethehardworkontheserversideandleavingthefun,coolstuffontheclient.Clientsaresortoflikeyourstarvingartistlittlesister,they'rebeautifulandfun,buttheydon'tdomuchwork.Withthatinmind,wehavechosennottoendorseanyoneGUIbuilder.Webelievethatthereisnosingletoolouttherethatcouldpossiblybeallthingstoallpeople.WhichGUIbuilderyouchooseisofnoconsequencetotherestofthischapter.RatherthanstepthroughtheJavacodefordesigningaGUI,wewillletyoujustdesigntheGUIaswedescribeinthissectionandthenwe'llmoveon.DefiningtheProblemOneofthethingsthatPrashantlikedbestaboutworkingatSunwastheirincrediblebreakrooms.Everybreakroomhasaniftylittlewatercooler.Now,thefirsttimeyoulookatit,you'llsaytoyourself,"Gee,bigdeal."But,wait,there'smore!Thatlittlewatercooleralsospitsoutwarmandhotwater!Whenyoufirstgazeuponthismarveloftechnologicalprowess,youwillbestymiedandgettheurgetowriteanapplettounveilyourdiscoverytotheworld.Thisispreciselywhatweintendtodo.Typically,youwillhavesomeinformationthatneedstobepublishedtotheoutsideworld.Intherealmofclient/servercomputing,thisisdonebycreatingaservertopublishthatinformation.Clientsarethenabletoaccessthatinformationthroughtheserver.Inourexample,wewanttopublishinformationaboutourwatercooler,andwewilldosobycreatingaclienttoaccessthatinformationfollowedbyaservertoprovideit.TheCoolerInterfaceDefinition Weneedtomodeltheinterfacedefinitionsothatitisintuitive.Forexample,ourIDLwillneedthreeoperations,oneforeachofhot,warm,andcoldwater.Weneedthreedataaccessorstogetthelevelofeachkindofwater.Withthatinmind,theinterfacedefinitionwouldlooksomethinglikethefollowing:interfaceCooler{intgetHotWaterLevel();intgetWarmWaterLevel();intgetColdWaterLevel();intgetHotWater();intgetWarmWater();intgetColdWater();};Wewillalsoneedtotrackerrorsininvocation,justincasethereisnowatertoget:interfaceCooler{intgetHotWaterLevel();intgetWarmWaterLevel();intgetColdWaterLevel();exceptionNoMoreWaterException{};intgetHotWater()throwsNoMoreWaterException;intgetWarmWater()throwsNoMoreWaterException;intgetColdWater()throwsNoMoreWaterException;};TheCoolerUserInterfaceOuruserinterfacewilldisplaythreebuttons,oneeachforhot,warm,andcoldwater.ByclickingontheHotWaterbutton,youwilldiminishthelevelofhotwaterinthecooler;clickingtheWarmWaterbuttonwilldiminishthelevelofwarmwater,andsoforth.Theserverwillstorethecurrentlevelofeachoneandmakesurewedon'ttakeoutwaterwhenthere'snonethere.So,theUIfortheCoolerclientisprettyobvious(seeFigure6-9),andyoucandrawitinjustaboutanyoftheGUItools.Figure6-9.Theuserinterfaceforourwatercoolerexampleisabasicthree-buttondisplay. Weshouldalsocreateanotherclientthatwatchestheserverandshowsthelevelofallthreewatersourcesatanygivenmoment.Thisway,ifwesticktheappletontheWeb,peopleallovertheworldcanseehowmuchwaterweSunemployeesactuallydrink.TheMonitorclientalsowillhaveabuttontoresetthewatersourcewheneverwefeellikeit(seeFigure6-10).Figure6-10.Oursecondclientdisplaysthelevelofwaterinourexamplecooler. Oncewearefinished,wehavetwoclientsbangingonthesameserver.Oneclientwillmodifytheserver,theotherwillonlydoqueriestotheservertogetinformation.Forterminology'ssake,wewillcallourWaterCoolerappletthesupplierandourMonitorapplettheconsumer(seeFigure6-11).Figure6-11.Ourtwoclientsoperatewiththesameservertocontinuallyupdateourinterface. ThefullsourcecodefortheclientisontheCD-ROMthataccompaniesthisbook,buttherearetwomethodsthatweneedtoimplementherefordemonstrationpurposes.TheInitmethodwillinitializebothclients,justasyouwouldanynormalJavaapplet.Wealsoneedanactionmethodtohandlebuttoneventswhentheyarrive.CAUTIONThesourcecodeweshowyouforJavaIDLispracticallypseudoCORBAcode.BecausewedonotwanttoendorseanyoneORB,wehavedecidedtoshowyouthemethodologyfordevelopingCORBAapplications.ThefeaturedappattheendofthechapterisimplementedusingImprise'sVisibrokerORB.Whenyouattempttoexecutetheotherexamplesonyourown,youwillneedtoconsultthedocumentationforyourORB,beitNEO,Visibroker,orOrbix,tobeabsolutelycorrectinyoursyntax.ThesourcecodeincludedontheCD-ROMforthecoolerprojectisNEOcode.Ifyouthinkthisisaproblem,youarecorrect.TheproliferationofORBs,andtheimpacttheycouldverywellhaveoverthecourseofthenextfewyears,leadsustobelievethatsomeone,somewhere,needstocomeupwithastandardlanguagemapping.Thissourcecodeportabilitywouldensurethateveryone'sCORBAimplementationlookedthesame.Afterall,theIDListhesameamongallofthem;whycan'tthesourcecodeforthatIDLbethesameaswell?publicvoidinit(){//doanyoftheUIstuffyouneedtodohere…}publicvoidactionPerformed(ActionEvente){Stringarg=e.getActionCommand();if(arg.equals(hotWaterButton)){}elseif(arg.equals(warmWaterButton)){}elseif(arg.equals(coldWaterButton)){}returntrue;} OnceyourUIworkstoyoursatisfactionandyouareabletogenerateevents,runwithinaWebpage,anddoalloftheotherfunstuffthatmakesJavasowonderful,youarereadytomoveontothenextstep.InitializingtheClientORBAtthispoint,youneedtotakeyourclientandplugitintotheORBsystem.Theactualstepsinvolvedindoingsoareprettysimpleandareoutlinedinthenextfewsections.Thefirst,andmostimportant,stepistoactuallyimporttheORBintoyourfiles:importcorba.*;OncetheORBisincluded,youcanhaveyourappletclassextendtheORB:publicclassCoolerextendsCORBAApplet{...}YouthenhavetoinitializetheORBsothatyourAppletispreparedtotalktotheORBitself.BecauseweextendtheORBtobeginwith,allwehavetodoiscalltheinitmethodforthesuperclass:publicvoidinit(){super.init();}Finally,yourinitmethodneedstoobtainareferencetotheremoteobjectwithwhichyouwouldliketotalk.Let'sassumethatwehavestoredtheobjectintheNamingServiceunderthename"Cooler":publicvoidinit(){super.init();coolerObject=NamingService.find("Cooler");} Nowthatwehaveareferencetotheobject,wecancommunicatewiththeremoteobjectjustasifitwerealocalobject.Aswewillsee,theJavasyntaxlooksexactlyasitwouldweretheremoteobjectalocalobject.InvokingaRemoteObjectNowthatwehavetheobjectandknowthattheserverisreadytobestarted,wecangoabouttheprocessoftalkingtotheobjectitself.UpuntilnowwehavecommunicatedonlywiththeNamingServiceinordertogettheobject;thiswillbeourfirstinvocationoftheobject.Notethateveniftheserverhasnotbeenstarted,theORBwillallowustotalktoit.ThisisbecausetheunderlyingCORBAmechanismmakessuretheobjecthasstartedandthatitisreadytobeinvoked.Sometimesthelatencybetweenaclientcallandaserverresponseislong,usuallybecausetheORBisintheprocessofstartingandinitializingaserverinordertohandletherequest.publicvoidactionPerformed(ActionEvente){Stringarg=e.getActionCommand();if(arg.equals(hotWaterButton)){coolerObject.getHotWater();}elseif(arg.equals(warmWaterButton)){coolerObject.getWarmWater();}elseif(arg.equals(coldWaterButton)){coolerObject.getColdWater();}returntrue;}Inthisexample,ourinvocationsareprettyobviouslytriggered.Foreverybuttonthatispressed,wewillmakearemotecalltoanobject.Thecallwillblocktheclientuntiltheserverletsgooftheinvocation.Ifwewantedasynchronouscommunicationratherthansynchronouscommunication,wewouldneedtotakesomestepsinourIDLfiletospecifythatacertainmethodshouldnotblockwheninvoked.Forexample,wecouldspawnathreadinsteadofmakingadirectinvocation.Forsimplicity'ssake,wehavechosennottodothis.However,ifyourserversidecodeiscomplicatedandtakessometimetoexecute,youmaywanttospawnthreadstohandleinvocationsforyou.TrackingErrorsJava'sexception-handlingmechanismswillenableustotrackandreporterrorswhentheyarrive.Furthermore,theexceptionhandlerswillpreventourprogramfromcrashingintheeventaserverencountersaproblemsomewheredowntheline.Ifthiswereamission-criticalapplication,theclientsidewouldnotexperienceanyproblemsshouldtheserverflakeoutforsomereason. Inordertomakethemosteffectiveuseoftheexceptionhandlers,youneedtodeclareyourownexceptionsintheIDLfile.Afterdoingso,yourserversmustthrowthoseexceptionswhennecessary.Thisenablesustoobtainaspecificexceptionforeveryerrorratherthanageneric"anerrorhasoccurred"message.publicvoidactionPerformed(ActionEvente){Stringarg=e.getActionCommand();if(arg.equals(hotWaterButton)){try{coolerObject.getHotWater();}catch(NoMoreWaterExceptionexc){//errorhandlinghere...}}elseif(arg.equals(warmWaterButton)){try{coolerObject.getWarmWater();}catch(NoMoreWaterExceptionexc){//errorhandlinghere…}}elseif(arg.equals(coldWaterButton)){try{coolerObject.getColdWater();}catch(NoMoreWaterExceptionexc){//errorhandlinghere...}}returntrue;}Asyoucansee,exceptionhandlingenablesustoprotectourclientsfromservermalfunctions.Italsogivesusthebenefitofthedoubtwhenmakinginvocationsthatcouldbedeemedrisky(i.e.,invocationsacrossmultiplenetworks,firewalls,andsoforth).ItispreciselythosespecialconditionsthatgivesCORBAthemostfitswhendealingwithnetworktraffic.ImplementingtheMonitorThemonitorisaclientinthesamewaythatthecoolerwecreatedpreviouslywasaclient.However,themonitorclientisalsorequiredtoroutinelyobtainthelevelsforeachkindofwatersothatitcandisplayeachlevelgraphically.Inordertoimplement thispingingeffect,weneedtopopathreadwithinwhichthemonitorwillquerytheservereverysecond:publicclassMonitorextendsAppletimplementsRunnable{ThreadmonitorThread=null;publicvoidstart(){if(monitorThread==null){monitorThread=newThread(this);monitorThread.start();}}publicvoidstop(){if(monitorThread!=null){monitorThread.stop();monitorThread=null;}}publicvoidinit(){super.init();coolerObject=NamingService.find("Cooler");}}Asyoucansee,wesimplyinvokeandcreateathread.Nowweneedtoaddtherunmethodinsideofwhichwewillpingtheservereverysecond.Whilethisisaverybrutishapproachtoretrievinginformationatasteadyratefromtheserver,itwillhavetosuffice.Inoursectiononcallbacks,wewillmodifythisclientsothatitobtainsinformationfromtheserveronlywhentheinformationhaschanged.publicclassMonitorextendsAppletimplementsRunnable{ThreadmonitorThread=null;publicvoidstart(){if(monitorThread==null){monitorThread=newThread(this);monitorThread.start();}}publicvoidstop(){if(monitorThread!=null){monitorThread.stop(); monitorThread=null;}}publicvoidinit(){super.init();coolerObject=NamingService.find("Cooler");}publicvoidrun(){//prioritizethemainthreadThread.currentThread().setPriority(Thread.NORM_PRIORITY-1);while(kicker!=null){//getthewaterlevelcoolerObj.getHotWaterLevel();coolerObj.getWarmWaterLevel();coolerObj.getColdWaterLevel();//pausethethreadtry{Thread.sleep(pause);}catch(InterruptedExceptione){break;}}}}ShuttingDownYourConnectionThefinalsteptocodingyourclientistoreleasetheobjectreference.InJava,thisisnotasmuchaconcernasitisinC++,foranymemorymanagementissuesareofnoconcern.Thisdoesnotmean,however,thatobjectreferencesare"free"inJava.Onthecontrary,theORBkeepstrackofeachobjectreferenceoutthere.Ifmultipleclientspossessobjectreferences,thentheserverwillhuntdownthenecessaryresources,allocatinganddeallocatingmemoryasitseesfit,inordertokeeptheserverfunctioningsmoothly.Bypreventingmultipleunusedobjectreferencesfrombeingallocated,yourservercanfunctionproperlyandtoitsutmostability.ClientOverviewInthissection,wehaveconstructedasimpleclient.Morecomplexclientswillfollowthesamemodel:Createtheuserinterfacefirst,thenfillintheCORBAdetails.Asyourclientsbegintogetmoreandmorecomplicated,youruserinterfaceandCORBAmoduleswillbegintointersect.Tomakedebuggingandperformancetuningmucheasier,itishighlyrecommendedthatyouconsidersplittingyourcodeaswedidinthefeaturedapplicationthatwedescribedinChapter1andthatwewillimplementusingIDLinafewsections. Nowthatyou'refamiliarwithcreatingandimplementingCORBAclients,let'sturnthetablesandseewhat'sinvolvedwithsettingupCORBAservers.Inorderforustosplitourprocessingappropriatelybetweentheclientandtheserver,theservershouldbethefocusofallourattention.Theclientshoulddonothingmorethanfunnelinformationbackandforthbetweentheuserandserver.Youshouldlimittheamountofprocessingyoudoinyourclient.Saveallthehardworkforyourserver.CORBAServersOneofthebeautiesofCORBAserversisthattheyarestartedupautomaticallybytheObjectRequestBroker.WhenweusedsocketsandRMI,wehadtostartourserversmanually,butherewesimplycreateourserver,registeritwiththeORB,andforgetaboutit.Everytimeaclientinvokestheserver,theserverwillstartup(ifitisn'trunningalready),initializeitself,andreadyitselfforinvocations.Totheclient,allofthishappensseamlesslyandwithnoadditionalworkneeded.DefininganInterfaceandGeneratingCodeIntheprevioussection,wedefinedourinterfaceasfollows:interfaceCooler{intgetHotWaterLevel();intgetWarmWaterLevel();intgetColdWaterLevel();exceptionNoMoreWaterException{};intgetHotWater()throwsNoMoreWaterException;intgetWarmWater()throwsNoMoreWaterException;intgetColdWater()throwsNoMoreWaterException;};Nowweneedtoimplementtheinterface.Thefirstthingweneedtodoistogenerateallourstubcode.ThestubcodeprovidestheunderlyingCORBAfunctionalitytoourserversothatwecanconcentrateondevelopingtheserverlogicitself.Becausewegeneratecode,wedon'tneedtoknowthenuancesofhowCORBAworks.JavaIDLincludesanidltojavacompilerthattranslatesIDLcodeintoJavacode.TheIDLfilethatwedefinedearliergetssixgeneratedanalogsthathandletheCORBAplumbingforus.First,theHolderclassisgenerated.Aswediscussedpreviously,aHolderallowsustopassaCORBAobjectasinoutandoutparameterstoCORBAmethods.WealsogetanOperationsclassthatdefinesasimpleJavainterfacefromwhichtheotherfilescaninherit.ThemeatofthegeneratedservercodeliesintheServant,Skeleton,andStubcode.TheclientusesaSkeletontoobtainabasicframeworkfortheobjecttowhichitdesirestocommunicate.TheSkeletonissortoflikearoadmap.Usingit,youcangetagoodideaofwhereyouaregoing,butyouwillgetnoinformationastothescenery alongtheway.ASkeletonenablestheclienttoknowwhatispossible,butnothowthatisaccomplished.BoththeSkeletonandtheServantusetheStubcodetohandletheinteractionoftheServercodewiththeORBitself(seeFigure6-12).WhiletheStubdoesallthework,theSkeletonandServantarewhatweactuallysee.Figure6-12.ThegeneratedcomponentsforaJavaIDLserver.AsyoucanseefromthediagraminFigure6-12,theStubisthefoundationoftheentireCORBAserver.TheotherclassesusetheStubtoobtaininformationabouthowtheywillimplementtheIDL.WewillseeinamomenthowJavaRMIclassesaregeneratedafterwecreatetheserverfile.JavaIDLworksverydifferently.WhereasRMIworksongeneratedclasses,IDLgeneratescodebasedontheIDLfile.Aswehavenotedbefore,interfacesdefinedusingtheIDLareinherentlylanguageindependent.WecouldjustaseasilyhavecreatedaC++serverasaJavaserver.WhenweusetheidltojavacompileronourCooler.idlfile,wegetthefollowingsixclasses:1.CoolerRef2.CoolerHolder3.CoolerOperations4.CoolerStub 5.CoolerServant6.CoolerSkeletonAswediscussedpreviously,eachoftheseclassesplaysanintegralroleinhowourserverbehavesundertheCORBAumbrella.Itishighlyrecommendedthatyounotmodifythesegeneratedfiles.CreatingtheServerImplementationOncewegeneratecode,weneedtocreateaclassthatwillcontaintheroutineswewanttoprovidewhenamethodisinvoked.UnlikeRMI,wecreateourserverafterwegeneratetheunderlyingcodefunctionalityforit.Theskeletons,stubs,andservantsare,astheirnamesimply,placeholders.Wemustsupplythelogicforourmethods;itjustdoesn'tappearoutofmid-air.Byconvention,ourserverclass'snamecontainsthenameoftheIDLobject,followedbythe"Impl"descriptor.Keepinmindthatwedon'thavetonameourclassCoolerImpl,butwedobecausethatisthegeneralCORBAconvention.Thefirststepincreatingourserveristoincludeallthegeneratedcode:importCooler.*;Oncewehavedonethat,wecreateaCoolerImplclassthatimplementstheCooler-Servantwegeneratedearlier.Insodoing,ourCoolerserverobtainstheCORBAplumbingprovidedbythegeneratedcode.importCooler.*;publicclassCoolerImplimplementsCoolerServant{}Now,weneedtofillinthenamesofthefunctionswemustimplementinordertofulfillourcontractwiththeIDLdefinitionandcreateaconstructor:importCooler.*;publicclassCoolerImplimplementsCoolerServant{CoolerImpl(){super();}publicintgetHotWaterLevel(){} publicintgetWarmWaterLevel(){}publicintgetColdWaterLevel(){}publicintgetHotWater()throwsNoMoreWaterException{}publicintgetWarmWater()throwsNoMoreWaterException{}publicintgetColdWater()throwsNoMoreWaterException{}}Finally,weneedtofillineachofthefunctionssothattheydowhattheyareintendedtodo.importCooler.*;publicclassCoolerImplimplementsCoolerServant{privateinthotWaterLevel;privateintwarmWaterLevel;privateintcoldWaterLevel;CoolerImpl(){super();hotWaterLevel=0;warmWaterLevel=0;coldWaterLevel=0;}publicintgetHotWaterLevel(){returnhotWaterLevel;}publicintgetWarmWaterLevel(){returnwarmWaterLevel;}publicintgetColdWaterLevel(){returncoldWaterLevel;}publicintgetHotWater()throwsNoMoreWaterException {if(hotWaterLevel>;=10)hotWaterLevel-=10;elsethrownewNoMoreWaterException;}publicintgetWarmWater()throwsNoMoreWaterException{if(warmWaterLevel>;=5)warmWaterLevel-=5;elsethrownewNoMoreWaterException;}publicintgetColdWater()throwsNoMoreWaterException{if(coldWaterLevel>=3)coldWaterLevel-=3;elsethrownewNoMoreWaterException;}}Die-hardCORBAveteranswillattesttothecharmingsimplicitywithwhichthisisdoneinJava.C++serverscontainthesamesteps,butcanbedrasticallymorecomplicatedthantheyneedtobe.Wehavenowcompletedthecreationofourserverimplementation.CreatingtheServerExecutableThecodewecreatedintheprevioussectionisknownasservantcode.Aservantisthephysicalprocessinwhichyourserverexecutes,andtheserverimplementationiscontainedtherein.AserveristhesetofinterfacesandmethodspublishedintheIDL.Theinterfacedefinitionisthecontractthattheserverfulfillsandtheservantexecutes.Thatsaid,wemustnowcreatetheserverforourCooler.Theservermustdothreethings:1.Startitselfupinaphysicalprocess.2.Createaservantinstancetoresideintheprocess.3.BinditselftoanameintheNamingService.Allthisisanalogoustoanordinarytablelamp.Thereareseveraltablelampsinyourhome,allofwhichimplementthesameinterface—namely"turnon"and"turnoff."Justbecausetheyallimplementthesameinterfacedoesn'tmeanthattheyallmustbethesamelamp.Indeed,youneedmanylamps;otherwise,youwouldtriponyourshoesasyouwenttobed.So,oncewecreateseveraldifferentlamps,weneedtoputthemintheirdesignatedlocationsandplugthemintothesocket.Likewise,oncewecreateaservant,weneedtoputitinsideaserverandplugitintotheORB.Todoso,firstwemustcreatetheclasssothattheservercanbeginexecutinginitsownprocessspace.Afterwecreateaclass,weneedtosupplyitwithamainroutine andlinkupwiththeORB.IfwedonotlinkupwiththeORBhere,subsequentinvocationsthatcreatethestubs,skeletons,andservantswillbeunabletoworkproperly.importCooler.*;publicclassCoolerServer{//privatevariablesprivateCORBAcorba;publicstaticvoidmain(Stringargv[]){//linkupwiththeORBcorba=newCORBA();}}Next,weneedtocreateaninstanceoftheCoolerImplservantclassthatwecreatedintheprevioussection.WealsoneedtousetheCoolerRefcontainerclasstosupportourservantinstance.Rememberthatclientsdon'twantservantstotalkto,theywantservers.Withservers,theygetasketchofthecontractprovidedforintheIDL.Withservants,theygetallthelegalmumbojumbointhecontractitself.Clientsdon'tneedtoknowthatstuff.importCooler.*;publicclassCoolerServer{//privatevariablesprivateCORBAcorba;privateCoolerRefcoolerRef;publicstaticvoidmain(Stringargv[]){//linkupwiththeORBcorba=newCORBA();//createtheservantclassCoolerImplcoolerImpl=newCoolerImpl();//createthecontainerclasscoolerRef=CoolerSkeleton.createRef(corba.getORB(),coolerImpl);}} Finally,theservermusttaketheCoolerRefinstanceandbindittoauniquenameintheNamingService.importCooler.*;publicclassCoolerServer{//privatevariablesprivateCORBAcorba;privateCoolerRefcoolerRef;publicstaticvoidmain(Stringargv[]){//linkupwiththeORBcorba=newCORBA();//createtheservantclassCoolerImplcoolerImpl=newCoolerImpl();//createthecontainerclasscoolerRef=CoolerSkeleton.createRef(corba.getORB(),coolerImpl);//bindthisservertotheNamingServicecorba.rebind("Cooler",coolerRef);}}Notehowthenamewehaveboundtoisthesamenamethatwereferredtointheprevioussectiononclients.Aftercompilingallourcode,wehaveaworkingserverthattheclientsinthepreviousandnextchapterscantalkto.RegisteringwiththeORBFinally,theCORBAserverwehavecreatedmustbeplacedinsidetheInterfaceRepository,thelocationofallobjectsknowntotheORB.WhentheORBreceivesaninvocationfromaclient,itlooksintheInterfaceRepositoryfortheproperobjectand,ifitisfound,startstheobjectupandreadiesitforinvocation.ConsultyourCORBAvendor'sdocumentationonhowtoregisteranORBwiththeInterfaceRepository.Forexample,inNEO,registeringanORBisassimpleastyping:%prompt%makeregisterServerOverviewAswedidforourclient,wecreatedasimpleCORBAserverthatacceptsinvocationsandpassesbackresults.Thisserveris,inessence,nodifferentfromthemostcomplexCORBAservers.Thestepsinvolvedincreatingserversremainthesame: 1.DefineyourobjectusingtheIDL.2.GeneratestubsandskeletonsfromtheIDL.3.Fillinthecode.4.Createtheservercontainerobject.5.Registertheobject.Insodoing,anyobjectserveryoucreatewillrunefficiently,willbeveryreliable,andwillhavetheflexibilitytobechangedoften.Sometimes,youdonotwantyourJavaIDLapplicationtobeafull-fledgedserver.Forexample,serverscannotbeembeddedwithinanappletand,therefore,cannotexistonaWebpage.Ifyoustillrequiredynamicupdatestoyourserver,theonlywaytogetthemistouseacallback,whichwe'lldiscussinthenextsection.CORBACallbacksLet'ssayyou'vebeenpesteringyourAuntFranaboutthedetailsforherlatestwedding.Youcallhereveryday,andsheisgettingsickofit.Finally,shetellsyouthatshewillcallyou"onlywhensomethinghappens."Inessence,thetwoofyouaresettingupcallbacksbetweenoneanother.WhenAuntFrangetsaneventthatyoushouldbeawareof,youwillgetacall.Otherwise,herphonewillbesilent,andshewillnotbebothered.JavaCallbacksJavaIDLenablesyourclientobjecttosenditselftoaserver,settingupareferencebridgetotheclientobject.Whenevertheservermusttelltheclientsomething,itwillmakecallsontheclientobjectsitstores.Inthismanner,aJavaIDLservercankeeptrackofalltheclientsthatarespeakingwithitandfunnelinformationbackandforthbetweentheobjects.Forexample,ifeverymemberoftheweddingparty,notjustyou,werepesteringAuntFran,shecouldtellthemallthatshewillcallwhensomethinghappens.AuntFranwillthenbeannoyedonlywhenaneventoccurs.Shewouldprobablymakealistofallthepeoplesheneedstocallandgodownthelistwhenthetimecomes.Likewise,aJavaIDLserverkeepstrackofallitsclientsandpreventsanoverloadofthesystem.Thealternativetocallbacksisforeachclienttoroutinelypingtheservereveryfewsecondsorsotogetinformation.Althoughthismethodologymayworkforoneortwoclients,whenseveralclientsstartharassingthesameserver,theserverandthenetworkbegintogetunnecessarilyburdened.Withcallbacks,thenetworktrafficishighonlywhenaneventoccurs,andneveratanyothertime.Ingeekterms,thisisreferredtoasscalability.Callbacksarescalablebecausetheyworkjustasefficientlyforseveralthousandobjectsastheydoforonlyafew.CreatingaCallbackInordertousecallbacks,youmustcreateanddefineacallbackobjectwithinyourIDLfile.Theclientthatneedstosetupacallbackmustfirstcontacttheserver.In orderforittobeallowedtocalltheserverandsetupacallback,theclientmusthaveaccesstoamethoddefinedforthatpurpose.Becausetheserveristheonethatwillregisterclientobjectsandcallthemback,theservermusthavethatmethodaspartofitssuiteofpossibleinvocations.interfaceCoolerCallback{voidwaterLevelChanged(inlonghotLevel,inlongwarmLevel,inlongcoldLevel);}interfaceCooler{intgetHotWaterLevel();intgetWarmWaterLevel();intgetColdWaterLevel();intgetHotWater();intgetWarmWater();intgetColdWater();//publicmethodforthecallbacklongregisterCallback(inCoolerCallbackcoolerCB);voidunregisterCallback(inlongcallbackID);};NoticehowtheregisterCallbackfunctioncontainsaCoolerCallbackobjectasaparameter.YourJavaclientwillimplementtheCoolerCallbackobject.WhentheJavaclientsendsitselfastheparameterfortheregisterCallbackinvocation,itisessentiallytellingtheserver,"I'mtheguythatyouneedtocallwhenyougetachange!"TheregisterfunctionalsoreturnsanintegerspecifyingtheIDoftheobject.Iftheobjecteverwantstounsubscribetocallbacks,itcangivetheserveritsIDnumberandtheserverwillremoveitfromitscallbacklist.Furthermore,theclientshouldimplementcallbackmethodsjustaswedidintheserversection.Inessence,thecallbackwillimplementservermethodswithoutserverinfrastructure.Theendresultisthatyourclientcanbeinvokedbyaserverasifitwereaserver,buttheclientneednotbeburdenedbytheoverheadofbeingaserver(seeFigure6-13).Figure6-13.Clientsmustfirstregisterthemselveswiththeserverbeforetheserverwillbeabletocallthemback. RegisteringaCallbackInorderfortheservertoinvokeacallbackonaclient,theclientmustfirstregisteritselfwiththeserverasacallbackobject.Thisisdoneintheinitfunction.Weneedtoremovethecodehavingtodowiththreadsfromournon-callbackclient,andinsteadplacethefollowinginvocationinourinitmethod.WemayalsoremovetheRunmethodbecauseweneednotbotherwithactuallymakinginvocationsontheserver.Inaddition,ourclientshouldimplementthecallbackobject:publicclassMonitorextendsCORBAAppletimplementsCoolerCallback{publicvoidinit(){super.init();coolerObject=NamingService.find("Cooler");intcallbackID=coolerObject.registerCallback(this);}}NoticehowwepasstheRegistermethodacopyofourownobject,aswediscussedearlier.TheMonitorclientisnowreadytobeinvokedbytheserver.Lateronwewillimplementtheactualcallbackfunctionthatenablesustoprocessthedatawereceive.TheJavaIDLservershouldthenkeeptrackoftheclientobjectinsomekindofstoragemechanism.Noneofthisisautomatic;theprogrammermustcodeitall.Inthefollowingexample,westoretheclientobjectinaVectorbecauseefficientsearchingisnotrequired.Weonlyneedtocallthemallbacksequentially.Thetwofunctionsinthefollowingcodeshouldbeaddedtoyourserverdefinitionfromtheprevioussection:importCooler.*;publicclassCoolerImplimplementsCoolerServant{privateinthotWaterLevel;privateintwarmWaterLevel;privateintcoldWaterLevel; //ourcallbacksprivateVectorcallbacks;CoolerImpl(){super();hotWaterLevel=0;warmWaterLevel=0;coldWaterLevel=0;callbacks=newVector();}publicintgetHotWaterLevel(){returnhotWaterLevel;}publicintgetWarmWaterLevel(){returnwarmWaterLevel;}publicintgetColdWaterLevel(){returncoldWaterLevel;}publicintgetHotWater()throwsNoMoreWaterException{if(hotWaterLevel>=10)hotWaterLevel-=10;elsethrownewNoMoreWaterException;}publicintgetWarmWater()throwsNoMoreWaterException{if(warmWaterLevel>=5)warmWaterLevel-=5;elsethrownewNoMoreWaterException;}publicintgetColdWater()throwsNoMoreWaterException{if(coldWaterLevel>=3)coldWaterLevel-=3;elsethrownewNoMoreWaterException;}publicintregisterCallback(CoolerCallbackcoolerCallback){callbacks.addItem(coolerCallback);}publicvoidunregisterCallback( intcallbackID){callbacks.removeItemAt(callbackID);}}Oncethecallbackisregistered,theservercancontinuewithitsexecutionuntilaneventistriggeredtowhichitmustrespond.WhenAuntFransuddenlydiscoversthatherhusbandturnsouttobetheChiaPetshedatedfivemonthsbefore,shecangodownherlistofweddingpeopleandcalleachofthemback.Inthesamemanner,wewillbeabletolookatourtableofcallbackobjectsandrespond.ReceivingandHandlingaCallbackInordertoreceiveacallback,youneedtosetupacallbackfunction.ThisisanalogoustogivingAuntFranyourphonenumber.Whensheneedstotellyousomething,shewillhaveaspecificplacetocallyou.Likewise,yourcallbackrecipientsneedtolettheserverknowwheretocall.Whentheservergetsanevent,itinvokesaremoteprocedurecallonthecallbackfunction,passinganyparametersasnecessary.Yourcallbackfunctionacceptsandprocessesthedatagiventoitbytheserver.Figure6-14offersanillustrationofthisprocess.Figure6-14.ThecallbackregistrationandinvocationprocessTIPRememberthatcallbacksareanoptiontoservers.Yourcallbackrecipientisactinglikeaserver,butitisnotquiteaserver.Itcannotbeinstantiatedonitsownbyaremoteobject.Eachindividualfunctionmustbesetupwiththecall-backserver,andtheflexibilityyouhadwithfull-fledgedserversiscompletelylost.Ontheotherhand,yourappletcanreceiveeventsfromaCORBAserverwithoutmuchoverhead,itcanbeusedwithinabrowser,anditiseasiertoimplementthanaserver. BecauseourcallbacksactuallyimplementtheCallbackObjectinterface,theyautomaticallyinheritthewaterLevelChangedmethod.OurclientshouldprocessallitsdatainthewaterLevelChangedfunction:publicclassMonitorextendsCORBAAppletimplementsCoolerCallback{publicvoidinit(){super.init();coolerObject=NamingService.find("Cooler");intcallbackID=coolerObject.registerCallback(this);}publicsynchronizedvoidwaterLevelChanged(inthotLevel,intwarmLevel,intcoldLevel){System.out.println("receivedacallback!");...handletheUIstuffyouneedto...}}Yourcallbackfunctionwillmerelyreceivethewaterlevelsforallthreekindsofwater.YoucantheneffecttheGUIhoweveryouplease.Noticehowweneveractuallyinvokeamethodontheserverafterweregister.Instead,wesitback,drinkourmartinis(shaken,notstirred),andwaitfortheservertocallus.AstheysayinHollywood,"Heybabe,don'tcallme,I'llcallyou."Tothateffect,theserverwillcontainwithinitthecodenecessarytoinvokethecallbackitself.Here,wehavechosentoinvokeonallthecallbackswheneverthewaterlevelischangedinanyway:publicintgetHotWater()throwsNoMoreWaterException{if(hotWaterLevel>=10){hotWaterLevel-=10;for(intx=0;x>callbacks.size();x++){//getthecallbackobjectCoolerCallbackcb=(CoolerCallback)callbacks.itemAt(x);//invokeonthecallbackobjectcb.waterLevelChanged(hotWaterLevel, warmWaterLevel,coldWaterLevel);}}elsethrownewNoMoreWaterException;}AsimilarmethodwillbeemployedforthegetWarmWaterandgetColdWaterfunctions.CallbacksinShortInordertoprocessinvocationsfrommultipleclientsefficiently,aservershouldideallysetupamechanismwithwhichitcancontrolhowinvocationsarehandled.Becausetheserverdoesthebulkofthework,itshouldgettocalltheshots.Withcallbacks,wecandowhatcorporatemanagementhasneverfiguredout.Thepeoplewhodoalltheworkgettomakeallthedecisions.Whatanovelidea!AJavaIDLVersionoftheFeaturedAppNowthatweknowhowtocreatefullIDLandCORBAserversalongwiththeclientsthataccompanythem,let'sputourtalentstouse.TheInternetcalendarmanagerwediscussedinpreviouschaptersisdividedintotwoparts:theNetworkclientmoduleandtheCalendarserverwithwhichthemodulewillcommunicate.First,wewillcreatetheclientandthenwewillcreatetheserver.Butbeforethatweneedtheinterfacedefinitionoftheserveritself.UnliketheversionofthisapplicationinthefirsteditionofthisbooktheCalendarapplicationhasbeenmodifiedtouseaMicrosoftAccessDatabasetostoreappointmentdata.JDBCisusedontheservertointeractwiththedatabase.TheloadDBmethodoftheserveriswhatinitializestheDatabase.TheexamplethatfollowswasmadeusingJDK1.3,JDBC2.0,andtheImpriseVisibrokerORB.ServerInterfaceThefollowingIDLoutlinesthemethodsignaturesoftheremotecalendarserverobject.Theservermayresideanywhereand,aswediscussedearlier,canberetrievedthroughtheNamingService.Fordemonstrationpurposes,we'llstoreourcalendarserverintheNamingServiceunderthename"CalendarObject."Noticehowwehaveenclosedourobjectwithinamodule.Themodulewillactasaholderforallofourcalendar-relatedobjects.Forexample,inordertoaccesstheAppointmentTypeobjectfromwithinJava,youwouldhavetospecifyCalendarIDL.AppointmentType.Aswediscussedinourearliersectiononlanguagemappings,modulesgettranslatedintoJavapackages.moduleCalendarIDL {structAppointmentType{stringreason;stringtime;};interfaceCalendar{voidscheduleAppointment(instringreason,instringtime);voidloadDB();typedefsequenceAppointmentList;AppointmentListgetAppointments();};};NetworkModuleAsyouwillrecall,theNetworkModulehasasimplesetofmethodswithwhichwecanchangetheserver.Itisinstantiatedbytheclientandtakesthehigh-leveldatastructuresgiventoitbytherestoftheclientandsendsitofftotheserver.Ourserverwillthenprocessinformationandmaintainstate.Wehaveincorporatedseveralmethodsthatwillenableustoaccesstheinformationontheserver.HereistheoriginalcodefortheNetworkModule.Notetheadditionoftheimportstatementtoincludeallthecalendar'sIDLserverfiles.Insodoing,wedonothavetospecifytheentirepackagenameforthecalendar'sfiles.importCalendarIDL.*;publicclassNetworkModule{publicvoidscheduleAppointment(Stringreason,inttime);publicVectorgetAppointments();publicvoidinitNetwork();publicvoidshutdownNetwork();publicvoidstartCorba(org.omg.CORBA.ORBorb);}Wewillnowimplementtheconstructorforthisobject.TheconstructorinitializestheconnectiontotheCORBAserverandsetsuptheremoteIDLobjectforusebytheotherroutines.WewillkeeptrackoftheremoteobjectwiththecalendarObjectvariable:publicclassNetworkModule {//makeacalendarobjectCalendarcalendar;NetworkModule(){org.omg.CORBA.ORBorb=org.omg.CORBA.ORB.init(args,null);calendar=CalendarHelper.bind(orb,"CalendarObject");calendar.loadDB();}publicvoidscheduleAppointment(Stringreason,inttime){}publicVectorgetAppointments(){}}WenowneedtofillinthefunctionalityoftheNetworkModule.Becausewe'vealreadyinitializedtheremoteobject,wecanfeelfreetouseitandcommunicatewiththeserver.InthegetAppointmentsmethod,wewillneedtotranslatethearrayofAppointmentTypeobjectstoaJavaVector.Wedothissothattherestoftheapplicationwillnotneedtobeawareoftheimplementationdetailsoftheserveritself.publicclassNetworkModule{CORBAServercalendarObject;NetworkModule(){String[]args;org.omg.CORBA.ORBorb=org.omg.CORBA.ORB.init(args,null);calendar=CalendarHelper.bind(orb,"CalendarObject");calendar.loadDB();}publicvoidscheduleAppointment(StringappointmentReason,StringappointmentTime){calendar.scheduleAppointment(appointmentReason,appointmentTime);}publicVectorgetAppointments(){//thevariabletostoreallofourappointmentsinVectorappointmentVector=newVector();CalendarIDL.AppointmentType[]appointment;if(calendar!=null){appointment=calendar.getAppointments();if(appointment.length!=0) for(inti=0;i0)?numberOfRows:1;appointment=newAppointmentType[numberOfRows];//corbahatesnullvalues,checkverycarefullyfor//anyuninitializedvaluesinti=0;while(result.next()){if(numberOfRows>i){appointment[i]=newAppointmentType();StringtmpOne="",tmpTwo="";appointment[i].time=""; appointment[i].reason="";if((tmpOne=result.getString("TIME"))!=null)appointment[i].time=tmpOne;if((tmpTwo=result.getString("REASON"))!=null)appointment[i].reason=tmpTwo;i++;}}//makesureeverysingleindexofthearrayhave//itstimeandreasoninitializedwhile(numberOfRows>i+1){appointment[i]=newAppointmentType();appointment[i].time="";appointment[i].reason="";i++;}}catch(SQLExceptionexc){System.out.println("NetworkModuleError:"+exc.toString());}//finalcheckagainstnullvariablesif(appointment!=null)returnappointment;else{appointment=newAppointmentType[1];appointment[0].time="";appointment[0].reason="";returnappointment;}}}Wemustnowcreateaserverprocessfortheservanttoexistinside.WedothisjustaswecreatedtheserverfortheCoolerexampleearlierinthissection.Insidetheapplicationmain,wewillinitializeCORBAandrebindtoauniquenameintheNamingService,inthiscase"CalendarObject."publicclassCalendarServer{publicstaticvoidmain(String[]args){//InitializetheORB.org.omg.CORBA.ORBorb=org.omg.CORBA.ORB.init(args,null);//InitializetheBOA.org.omg.CORBA.BOAboa=((com.visigenic.vbroker.orb.ORB)orb).BOA_init();//Createthecalendarobject.CalendarIDL.Calendarcalendar=newCalendarImpl("CalendarObject","jdbc:odbc:Calendar");//Exportthenewlycreatedobject. boa.obj_is_ready(calendar);System.out.println("Calendarserverisready.");//Waitforincomingrequestsboa.impl_is_ready();}}Wewillthenneedtoregistertheserver.YouwillonceagainneedtoconsultthedocumentationfortheORBvendoryouhavechosentofindouthowtodothis.Onceregistered,youcanrunyourclientandneveragainbelateforanimportantmeeting.DifferentVendors,DifferentProblemsBecauseoneofthebiggestdrawbackstoCORBAisthatthereareseveraldisparatevendorsforJAVAIDL,theOMGcreatedacomplexprotocolwithwhichobjectscancommunicate.TheInternetInter-ORBProtocol,orIIOP(pronouncedeye-op),isthe"language"usedbyobjectstoexchangeinformation.ItisbasedonTCP/IP,asopposedtoUDP,andformsacommonbaseforallCORBAclientsandserverstocommunicate.You,theapplicationprogrammer,willneverseeIIOP,andyouwillneverknowthatIIOPisgoingunderthecovers.However,theObjectRequestBrokerusesIIOPtofunnelinformationtootherORBs.Insodoing,aVisigenicORBandanIonaORBcantalkthesamelanguage,sotospeak,whencommunicatingwithoneanother.So,IIOPaddressesonemajorissue,theinteroperabilityofobjectswrittenfordifferentORBs,withdifferentCORBAimplementations.However,onemoremajorproblemstillexists.CORBAappletsoftenhaveseriousdownloadperformanceproblems.BecauseanORBmustexistoneveryplatformwithaCORBAclientorserver,CORBAappletsmustinclude,aspartoftheirimplementationclasses,theentireORB.Insodoing,aCORBAappletmustdownload400orsoJavaclassesthatconstitutetheORB.AswediscussedinourChapter1sectionon"Performance,"400classesisamajordatatransferasfarasJavaappletsareconcerned.Tosolvethisproblem,theNetscapebrowserincludes,aspartofLiveConnectandaspartoftheNetscapeclasses.zipfile,theentireImpriseVisibrokerORB.ThiswillallowthebrowsertorefrainfromdownloadingtheentireORBinaCORBAapplet,creatingagreatperformanceboostforCORBAapplets.However,whatiftheCORBAappletwaswritteninanon-VisibrokerORB?Well,atthatpoint,NetscapehasnochoicebuttodownloadtheentireORBasitwouldhavedonewithoutthepresenceofVisibroker,negatingany performanceboost.EventhoughIIOPaddressesinteroperabilityonaprotocolandcommunicationlevel,noCORBAvendorhasyettoagreeoninteroperabilityonanobjectsourcelevel.Asofthisbook'spublication,manyofthevendorswerestillnegotiatingontheexactcontentsofthatso-called"JavaIDL"thatwouldthenbeincorporatedaspartoftheJavaDeveloper'sKit.SummaryCORBAisquicklybecominganindustrystandard.WithindustrygiantsSun/NetscapeAlliancefirmlybehindthetechnology,itmaysoonmakeanappearanceinourregularprogrammingdiet.EventhoughJavabeginstonegatesomeofCORBA'sdifficulty,CORBAisstillalongwayfrombeingstandardfareoneveryone'sdesktopbecauseofstaunchcompetitionfromitsJava-onlybrother,JavaRMI.Chapter7.WebServers,Server-SideJava,andMore•InsideanHTTPServer•CommonGatewayInterfaceandCGIScripts•Servlets•DynamicDocuments•AServletVersionoftheFeaturedApp•JavaServerPages•MultipurposeServersWhatifyournormalWebserverwascapableofprovidingdynamicnetworkcontent?Ifitcouldgooutandconnecttootherdistributedobjects,usingsolutionsfromearlierinthisbook,itwouldbeabletofunnelinformationtoaclientwithouttheclientevenonceknowingofthemachinerybehindthescenes.Sofarwehavediscussedalternativesthathavebroughtnetworkedcomputingtotheclientsidewhilecreatingspecificclientapplicationstoacceptthatinformation.WiththeJavaWebServer,aservlet,inessenceaserver-sideapplet,canfunnelinformationbacktoaWebbrowserasastandardHTMLfile.Thebrowserneednotknowanythingaboutobjectdesign,internalmachinery,orevenwhataservletis.Inthischapter,wewillexplainthebasicfunctionalityofanHTTPserver,followedbyabrieftutorialonservletsandhowtomodifyservletstobeanobjectserver,likeCORBAorRMI,atthesametime.TheWebserversandtheservletarchitectureisanexcitinguseoftheJavalanguagethatwehavecometoknowandlove.Theexamplesinthischapteraredesignedtobringthatexcitementandfunbacktoyou.InsideanHTTPServerAswewillseeinamoment,JavaWebServerisnothingmorethananenhancedWebserverproduct.ThefactthatitiswritteninJavadoesnotdistinguishitfromMicrosoft'sownBackOfficeWebserverorNetscape'sCommerceServer.JavaWeb Serverprovidesdynamiccontentwithouthavingtoemploythecumbersometoolsthatwehaveseenthusfar.But,whatisanHTTPserveranyway?Whatdoesitdo,andwhatpurposedoesitserve?WebServerArchitectureAtitsmostbarebonesandmostbasiclevel,anHTTPserversimplylistensforclientrequestmessagesonthe"well-known"HTTPport(80)andreturnsresults.Theinteractionbetweentheclient(browserorapplication)andtheHTTP(Web)serverisgovernedbytheHypertextTransferProtocol(RFC1945HTTP/1.0,RFC2616HTTP/1.1).ItdoessobyclingingtothepredesignatedHTTPportandawaitingrequests.HTTPrequestsaretypicallyoftheform"GETfilename."Whenpresentedwithsucharequest,theHTTPserverwillsearchitsdocumenttreefortherequesteddocumentandreturnittotherequestingclient.Thegeneralpublic'sperspectiveofwhatisgoingonis"they'reontheWeb"andhaven'tthefaintestideathattheyareparticipatinginclient/servercomputing.TheportionoftheWebserverthatlistensforfilerequestsiscalledanHTTPdaemon.Adaemon,aswediscussedinaChapter1sectiononthreads,isaspecialprocesswhoseentireroleistohangaroundwithnodistinctstartuptimeandnodistinctshutdowntime.Ithasaspecificrolethatitplays,inthiscasetofetchfilesandreturnthemacrossanetwork,butdoessowithoutanyspecialhoopla.Moreoftenthannot,aWebserverwillhandlemultiplerequestssimultaneously(seeFigure7-1).Theserequestscanbefromthesameclient(browser)asinthecaseofthedeliveryofanHTMLfileandthegraphicsthatareembeddedinitorfrommultipleclients.Figure7-1.Webservershandlerequestsformultiplefiles.Oncethedaemongetsarequest,itwillgoandgetthefileandreturnittotherequester.Aswediscussedinourchapteronsockets,thisisapipe,ortwo-wayconnectionbetweentheclientandtheserver.TheHTTPProtocolSofarwe'vebeenusingtheHTTPacronymprettyfreelywithoutreallyunderstandingwhatitisorhowitworks.HTTPisarelativelystraightforwardclient/serverprotocolmadeupofclientrequestsandserverresponses.Itisalso"stateless"meaningthat fromonerequestandreplytothenextthereisnopreservationofstate(asinprogramstatebetweentheclientandserver).RememberthattheprimarygoalofanHTTPclientrequestistoretrievealltheresources(text,formattingandlayoutinstructions,andgraphics)neededtopresentaWebpagetotheclientuser.Eachclientrequestrequestsoneandonlyonethingfromtheserver;thismeansthatgettingeverythingneededbythelayoutandpresentationengineinyourWebbrowsermaytakemanyrequests.ThebasicHTTPrequestismadeupoftwoparts:arequestheaderandtheactualdatarequest.Therequestheaderincludesinformationaboutyourbrowserandoperatingenvironment.Theactualdatarequestismadeupofacommand(GET,POST,orSTAT)andaUniformResourceLocator(URL,RFC1738,RFC1808).HTTPURLsarealittlemorecomplicatedthanthesimpleURLsthatwe'veseenpreviouslyinthisbook.AnHTTPURLconsistsoftheprotocol(http,ftp,mailto,ldap),thehostname,thedomainname,theporttheWebserverislisteningon(thewell-knownportforHTTPisport80),thepathtotheresourcebeingrequested,andanyparametricinformationthattheresourcemightneed.Uponacceptingaclientconnection,theWebserverreceivestherequestheaderandstorestheclientenvironmentalinformation;itthenreceivestheactualrequest.Theserverthenshutsdowntheconnectiononport80,spawnsathread,andopensanotherconnectionbacktotheclientonanon-well-knownport(>1024)toreturnthedataon.Thisisdonetominimizethetimethatport80istiedupandtomaximizeitsavailabilitytoreceiveotherclientrequests.Thesamethinghappensineveryinstanceofthethread;theserversearchesitsdocumenttreefortherequestedresource(typicallyafile)specifiedintheURL.Inrespondingtothe"GET,"theWebserverbuildsaresponseheader(serverenvironmentalinformationandstatusoftheoveralltransaction)andsendsitbacktotheclientimmediatelyfollowedbyeithertheresourcefromthedocumenttreeoranerrorindication.UsingaWebServerToday,weuseaWebbrowsertogetstaticdocumentcontent.Theservergetsarequestfromthebrowser,findsthefileitislookingfor,andreturnsittothecallingbrowser.ThisisthewaytheWebworkstoday.Morethanlikely,theWebwillshifttomoredynamicdata.Data(essentiallyHTMLfiles)todayiscreatedbeforehand,placedonaserver,anddownloadedbyclients.Eventually,theWebwillmovetoapointwheretheinformationisnevercreatedbeforehand,butgeneratedonthefly.Itwillfacilitatesmall,efficientprogramsthatcreatedynamiccontentforyouandhelptopreventthetimelydistributionofdata.HowmanytimeshaveyougonetoaWebpageandfoundthelinkunattachedorthefileoutdated?Withdynamicdata,youcanassurethatthefileisgeneratedtodayratherthanfiveorsixmonthsago.AsyoucanseeinFigure7-2,theshifttoexecutableratherthanstaticcontentontheWebisactuallyprettyeasytodo.ThenextfewsectionswilloutlinetheJavaanswertothisparticularWebserverquestion. Figure7-2.TheWorldWideWebmovestoexecutablecontent.AdvancedWebServerFeaturesTheWebserversoftodayalsoincorporateseveraladvancedfeaturessuchassecurity,performanceenhancements,andadministration.SecurityisdiscussedindetailinChapter13,"JavaandSecurity,"and,indeed,manyoftheJavasecurityconcernsthathavecroppedupoverthelastfewyearsstemfromconcernsovertheWebserveritself.WillsecureelectronictransactionsactuallyworkovertheWeb?TheseareissuesthatwillbedealtwithbytheWebservercommunityfarbeforetheyareincorporatedintoJavaitself.Performanceenhancementsarecreatedduelargelytosmartermultithreadedenvironments,fasterhardware,andmorecapablenetworkconnections.Often,aWebserverisperformancetunedbyspawningathreadforeveryHTTPrequest.Finally,networkadministrationisanissueinandofitself,butWebnetworkadministrationembodiesmorethanthatofitstraditionalfather.Networkadministrationdealslargelywithlocalareanetworks.WithWebservers,thenetworkadministrationissuesareexpandedonawiderscale,overWideAreaNetworks.Whathappenswhenmachinesfail,orwhenHTTPserversgetoverloaded?AsadvancesinhardwarefailovertechnologyandJavaNetworkManagementareunveiled,theWebadministrationwillcontinuetogeteasier,butatthesametimemorecomplex.HTTPServerOverviewTheHTTPserveristhemostcommonmeansnormalpeopleusetoharnessthepoweroftheInternet.ButeventhetriedandtrueHTTPserverismovingawayfromthesimplicityofservingstaticdata.TheWebasawholeismovingtowardexecutablecontent.ServletsgiveusawaytoprogramtheserversideofanHTTPconnection.Today,wehaveseveralalternativesrangingfromWebbrowserstoFTPclientsthatallowustoplugintothenetwork.What'sbeenlackingistheserver-sideconnectiontothatinteractivecontent.CommonGatewayInterfaceandCGIScriptsDiggingbackintothehistoryoftheInternetalittlebit,wefindthatbeforetheWebandWebbrowsersandgraphicalcontenttherewassomethingcalledGopher.WhentheprimaryusersoftheInternetweretheuniversitiesandtheresearchcommunityapurelytext-basedWorldWideWebexisted.Thisweballowedusers(usingaGopher clientorfortherealgeeksasimpleTelnetclient)tosearchforandretrievetextualdocumentsfromlargetext-basedrepositoriesallovertheworld.SincetheadventofthegraphicalWebbrowseranddefinitionofHTML,GopherhastakenabackseattoHTTP,butinmanyuniversities(especiallyinthefarEastandthirdworld)Gopherisstillaliveandwell.ThewaythatGopheralloweduserstosearchtheselargetextrepositorieswastoprovidetheGopherserverswithamechanismthroughwhichausercouldrequesttheservertorunaprogramasachildprocessoftheserver.Toprovideadefinedinterfacebetweentheserverandtheapplicationtoberun,theCommonGatewayInterfacespecificationwasdeveloped(seehttp://hoohoo.ncsa.uiuc.edu/cgi/forthespecification).BasicallyCGIdefinesasetofenvironmentvariablesmadeupoftheenvironmentalinformationcontainedintherequestandresponseheadersexchangedbyHTTPclientsandservers.Asasetofsystemenvironmentvariables,thisinformationisavailabletoanyapplicationwritteninanyprogramminglanguagethatissupported.QuiteoftentheseprogramsarewritteninoneoftheUNIXshelllanguages,andtheybecameknownasCGIscripts.Today,itiscommontohearanyprogramthatisrunbytheWebservercalledaCGIScriptorCGIProgram.CGIisaveryimportanttoolinourWebprogrammingtoolkit.Onceyouunderstandtheinformationprovidedintheinterfaceandcanenvisionwhatyoucoulduseitfor,itbecomesapparenthowyournamegotonso-and-so'se-maillistafteryouvisitedso-and-so'sWebsite.InterrogatingtheHTTP_USER_AGENTfromourCGIprogramallowsustodetermineonarequest-by-requestbasisthebrowserbeingusedbytheenduserandallowsustocustomizedynamiccontenttobestexploitfeaturessupportedbyspecificbrowsers.Table7-1.CGIEnvironmentVariablesSERVER_SOFTWARENameandversionoftheserversoftwareSERVER_NAMEServer'shostname,DNSalias,orIPaddressGATEWAT_INTERFACETheversionofCGIbeingused(CGI/1.1)SERVER_PROTOCOLNameofandrevisionofSERVER_PORTprotocolrequestwasreceivedas(HTTP/1.1)REQUEST_METHODPortnumberbeingusedbytheserverPATH_INFOTherequestmethod"GET","HEAD","POST"PATH_TRANSLATEDThepathportionoftherequestSCRIPT_NAMENormalizedversionofthePATH_INFOQUERYSTRINGVirtualpathtothescriptREMOTE_HOSTParametricinformationattachedtotheURLREMOTE_ADDRIPaddressofREMOTE_HOSTHostnameoftherequestinghostAUTH_TYPETypeofclientauthenticationprovidedIfserversupportsauthenticationandthescriptisREMOTE_USERprotected,thisistheusernametheyhaveauthenticatedasRemoteusernamefromtheserverifitsupportsREMOTE_IDENTRFC931CONTENT_TYPEUsuallytheMIMEtypeoftheretrieveddata CONTENT_LENGTHLength(inoctets/bytes)ofthedatabeingreturnedHTTP_ACCEPTMIMEtypestobeacceptedbytheclientHTTP_USER_AGENTClientbrowsernameandversionBeforeJavaWebServersandWebserverswithbuilt-inJavasupport,aJavaprogramcouldberunasaCGIprograminaslightlyroundaboutwayaslongastherewasaJavaVirtualMachineavailableontheWebserver'shostmachine.ThewayitwasdonewastocreateashortscriptthatwouldloadtheJVMandthenruntheJavaapplicationontheJVM.Forinstance,onanNTplatformthathadtheJVMinthesystempath,thescript(.batfile)wouldcontainthesinglestatement:"javamyprog"Typically,whenaCGIprogramisrunasachildprocessoftheWebserver,anythingwrittento"sysout"iscapturedbytheWebserverandreturnedtotheclient.InJavathen,tocreatedynamicHTMLtobereturnedtotheclient,allweneedtodoisusetheSystemobjecttowriteourcontent.System.out.println("MyCGI");System;out.println("...jdbcqueryresults...");ThismethodofrunningJavaontheserversidewascrudeandrudeandsufferedthesameproblemasCGIscriptswritteninC,C++,orscriptinglanguages(i.e.,aschildprocessesoftheWebservertheyareextremelywastefulofmachineresources).HavingtoloadtheJVMeachtimethe.batfilewasexecutedalsomeantthatperformancewasalsoprettybad…butitdidwork.ThenewWebserversaddressthiswithsupportforservlets;i.e.,server-sideJavaapplicationsthatdynamicallyproduceHTML,dodatabasequeries,andintegratethetwo.ServletsUntilnow,anHTTPserverhasfunctionedsolelytoprovidetheclientwithdocuments.Thedocuments,usuallywritteninHTML,perhapswithembeddedShockwaveorJavafunctionality(intheformofapplets),havebeenstaticallycreateddays,weeks,evenmonthsbeforetheclientactuallyfetchedit.Ifyouwanttocreatedynamicdocumentcontent,youmustusetheCommonGatewayInterface.CGIscriptswereahackdesignedtoprovidetwo-waycommunicationviatheWorldWideWeb.ServletsreplacetheneedforCGIscriptsandgiveyouamuchcleaner,morerobustalternative.WhatIsaServlet? ServletsareJavaapplicationsthatresideontheserversideofanHTTPserver.MorelikelythannotyoucreatedseveralJavaobjectsdesignedtobeusedbytheclient.Typically,theseJavaobjectsarerestrictedbysecurityconstraintsthatchallengeyourabilitytousefilesandnetworksonawhim.ServletsarenotsubjecttoartificialsecurityrestrictionsandenableyoutoextendtheeasynatureofJavaprogrammingtotheserversideofanHTTPconnection(seeFigure7-3).Figure7-3.Servletscreatedocumentsontheflyratherthangettingdocumentsthatwerealreadythere.ServletscanbeusedtocreatedynamicHTMLdocuments.Thedocumentsgeneratedbyaservletcancontaindatagleanedfromothersources,includingremoteobjects,databases,andflatfiles.Aswewillseeinalatersection,servletsalsocanbeintegratedwithyourexistingRMIorIDLserver.Furthermore,theinvestmentoftimerequiredtolearnservletprogrammingisnegligiblebecauseknowingJavaautomaticallyensuresthatyouwill"know"servlets.So,whydon'twejustuseRMI?NormalJavaobjectshavewell-definedpublicinterfacesthatcanbeusedbyavarietyofclients,includingWebpages,otherapplets,evenCORBAservers.TheseJavaobjectsareconventionalobjectsthatareinstantiatedeverytimeoneisneeded.Intheend,ifyoucreateanobject,youverywellcouldhavefiveorsixcopieshangingouttherebeingusedbyobjectrequesters.Servlets,ontheotherhand,havenodefinedinterfaces.TheyarefacelessJavaobjects.TheJavaWebserversimplymapsarequestontoaservlet,passingittheentireURL call.Theservletthendoeswhatitisprogrammedtodoandgeneratesdynamiccontent.Servletscannothaveaninterfaceasweknowit.Instead,allitsfunctionalityisrestrictedtoonefunctionwithinitsclasshierarchy.TheServletAPITheServletAPImapseachservlettoaspecificHTTPrequest.MostcurrentlyavailableWebserverssupporttheServletAPI.ThisisdoneinmuchthesamewaythattheWebserversupportsCGIprograms.IntheWebserveradministration,thereisanoptionthatyousettoindicatethatyouaregoingtouseservlets;thiswillhavetheWebserverstartuptheJavaVirtualMachineaspartofitsstartupprocess.Elsewhereintheadministrativeportionwillbeaplacewhereyoucanidentifywhereyouwishtolocatethe"magic"/servlet/directory.TheWebserverisresponsiblefortakingthemappingandinvokingtheproperservlet.Servletscanbeinitialized,invoked,anddestroyeddependingontherequest.TheJavaVirtualMachinebeingrunbytheWebservermakessurethattheservletcarriesoutitsinstructionscorrectly.Furthermore,becauseservletsareimplementedinJava,theyareplatform-independentandarchitecture-neutral.AswithnormalJavaobjects,servletsrequireavalidJavaVirtualMachinetobepresentonthemachineonwhichitruns.Inaddition,theservletrequiresaWebserverthatiscompliantwiththeServletAPIspecification.MostWebservershaveanumberof"magic"directoriesthatareusedforspecialpurposes.Themagicdirectory"cgi-bin"canbephysicallylocatedanywhereontheWebservermachine(D:executablesperl)butwillberelocatedto/cgi-bin/bytheWebserver;theservletdirectoryisanother"magic"directory,theWebserveradministrationclientwillallowustomapanydirectoryweliketo/servlet/.Inadditiontothe"magic"directoriesof"cgi-bin"and"servlet,"WebserversalsosupportafeaturecalledAdditionalDocumentDirectories;thisfeatureallowsustosetupourownnametodirectorymappings.Forinstanceyoumightfinditusefultosetupyourown"magic"directorycalled/javascript/tostoreallofyourembeddableJavascriptfiles.TheconceptofdirectorymappingbecomesmoreimportantaswemakemoreandmoreofourWebpagesdynamicandourdatabasesinteractive.WithmoredynamicallycreatedpagesonourWebsites,weneedmoreservers.IfourWebserversarealsoclientstoourLocalAreaNetworksorsharedfilesystems(liketheAndrewFileSystem—AFS),wecanhavemultipleWebserversserveourapplicationobjectsfromthesameshared"magic"directories.Thisensuresthatallusersaregettingthesameversionsoftheobjectsandispartofanoverallconfigurationmanagementscheme.NOTETheservletAPIiscurrentlypartoftheJDK1.2andconsideredapartofJava2.0. ObjectsthatwanttobedynamicinformationprovidersshouldimplementtheservletinterfaceshowninFigure7-4.InthediagraminFigure7-4,thoseobjectsthatprovidethefunctionalitydefinedintheservletinterfacearecapableofhandlingServletRequests.Figure7-4.TheServletclasshierarchygivesyoueasyaccesstoinputandoutputstreamsfordynamicdocuments.TheServletRequestobjectcontainstheentireHTTPrequestpassedtotheservletbytheJavaWebServer.TheServletRequestisalsocapableofextractingparametersfromtheHTTPrequestitself.Forexample,thefollowingURLcontainsfourelements:http://watson2.cs.binghamton.edu/servlet/steflik.html?coursesFirst,therequestdefinestheprotocolbeingused.Here,weusethehypertexttransferprotocol.TheHTTPrequestisfairlyubiquitousontheWebthesedays,butasnewprotocolssuchastheLightweightDirectoryAccessProtocol(LDAP)becomemoreprevalent,thisportionoftherequestwillbecomemoreandmoreimportant.Wethenseethedomainnamefortherequest.Inthisinstance,weaccesstheWebsitewatson2.cs.binghamton.edu,presumablytocheckwhatcoursesSteflikisteachingthissemester.Obviously,thisportionoftheaddressvarieswidelyfromsoftware developmentorienteddomainslikejava.sun.comtoeducationorienteddomainslikehttp://binghamton.edu.Finally,weaccessthedocumentanditsparameters.TheJavaWebServermapsthesteflik.htmldocumentrequesttoaservlet,passingtheparametercoursesaspartoftheServletRequestdatastructure.Keepinmindthatthephysicaldocumentsteflik.htmldoesnotactuallyexist;itwillbegeneratedontheflybytheservlet.ResponsesaresentbacktotherequestingclientviatheServletResponseobject.TheJavaWebServertranslatestheServletResponseobjectintoadynamicdocumentofsomekind.Wewillseelaterhowwecangeneratedynamicapplets,butwewillstillpassthedatabackthroughaServletResponseinstance.WhyNotCGIScripts?CGIscriptsarelanguage-independent.TheycanbewrittenineverythingfromC++toPERLtoAWK.ScriptsimplementingtheCommonGatewayInterfacesimplypassenvironmentvariablestooneanotherallthewhilegeneratingdynamicdocuments.Theycanprovideatonoffunctionality,aswehaveseenwiththeexplosivegrowthoftheWeb.CertainlywithoutCGIscriptstheWebcouldneverhavebecomeatwo-wayformofcommunicationthatwasreadilyacceptedbythegeneralpublic.CGIscriptshavetwomajordrawbacks,however.First,theysufferfromhorribleperformance.Theyareturtleslowandarenotscalable.MultipleCGIrequestsonthesameserverendupcreatingnewprocessesforeachrequest.TheendresultisthatCGIprocessesdonotcooperatewithoneanotherasthreadedapplicationswould.Instead,theyhogsystemresourcesandslownotonlythescriptsthemselvesbuttheHTTPserverthathostsitaswell.CGIscriptsarealsocompletelyplatform-dependent.Althoughthelanguagewithwhichtheyarewrittencanvary,theycannotbetransportedfromaWindowsmachinetoaMacintosh.Theyarewrittenonce,andusedinoneplace.TheJavaServletinterfaceprovidesanalternativetothismorass.BecausetheyarewritteninJava,servletsareplatformindependent.Theycanbemovedbetweenmachineswitheaseandwithoutrecompiling.Servletsalsocantakeadvantageofcleverthreadingmechanismsandprovidefastturnaroundandefficientprocessingofdata.OneotherthingaboutCGIisthatitiseasytohangupaWebserverwithascriptthathasnotbeenwellwrittenandtested;becauseservletsrunasathreadoftheJVMandnotasachildprocessoftheWebserver,theyaresafer.ServletsOverviewThesedays,HTTPserversarecommoditiestobehadinmuchthesamewayasapairofNikeAirJordans.YoucangetHTTPserversfromNetscape,fromMicrosoft,evenforfreeviatheWorldWideWeb.CompanieswhosesoleproductisaWebserveraredoomedtofailure.InanefforttoprovideanewkindofWebservertotheWebsurfingpublic,SunMicrosystemshascreatedtheJavaWebServerarchitecture. Servlet-compliantWebserversgeneratedynamicdocumentsthroughnormalprotocolrequests.Javaobjectsknownasservletscreatethedynamicdocuments.Aswewillseeinthenexttwosections,servletsarebotheasyandfuntowrite.Withoutmucheffort,youcancreateadynamicdocumentserverthatwillrenderyourCGIscriptingtechniquesofthepastobsolete.DynamicDocumentsWespokeearlierabouttheJavaWebServertranslatingdocumentrequestsintoservletcallsthat,inturn,createandpassbackadocumentcorrespondingtotherequest.Theservletmustbecapableofacceptingdifferentparametersfromtheclientandalsobeabletoformulatearesponsequicklyandefficiently.Byusingservlets,wewouldnothavetocreatethosedocumentsdays,weeks,perhapsevenmonthsinadvance.Rather,wesimplycreateaprogramthat,givenasetofparameters,cangenerateadocumentatthemomentoftherequest.Insodoing,wegenerateup-to-the-minuteinformationwithoutresortingtosoftwarehackslikeCGIscripts.CreatingtheServletAllservletsneedtoinheritfromtheServletorHTTPServletbaseclasses.ThedifferencebetweenthesetwoclassesisthattheServletclassismoregenericandcanbeusedwithRMIandCORBAobjectsasdatasources,whereastheHTTPServletfocusesonHTTPandinterfacingwithWebservers.ThebaseclasscreatesallthefunctionalityrequiredtomapJavaWebServerrequestsontoaphysicalservletprocess.Theservletprocessisstartedautomaticallybytheserverifitisn'tyetrunning.Anysubsequentrequestsontheservletprocesscaneitherbequeueduntiltheservletisreadytoprocessitortransferredtoanotherservletwhereitcanbestartedupandprocessed.Theseareadministrativetasksthatwewilldiscussinamoment.Meanwhile,weneedtoimplementtheservletarchitecturetoretainarequest,processdata,andsenddocumentsback.Let'ssaywewanttomakeaservletthatwillacceptarequestfromourfavoriteWebbrowserandechobacktousaWebpagecontainingsomeoftheinformationcontainedintheHTTPRequestHeader.Thisexerciseisinformativenotonlyaboutwritingourfirstservletbutalsoaboutwhatinformationisincludedintherequestheaderandhowwecanextractit.WestartbycreatingtheGetBrowserDataServletobjectthatextendstheHTTP-Servletbaseclass.Aswementionedbefore,theHTTPServletbaseclassisrequiredforallservletsandimplementstheunderlyingHTTPtoservletmechanisms.publicclassGetBrowserDataServletextendsHTTPServlet{}HandlingJavaWebServerRequestsEveryobjectthatinheritsfromtheHTTPServletbaseclassmustimplementtheservicefunction.Theservicefunctionhastwoparameters,anHttpServletRequest objectandanHttpServletResponseobject,andcanthrowoneoftwoexceptions,eithertheServletExceptionoranIOException.TheHttpServletRequestobjectgivesusinformationabouttherequestsenttous,particularlywhatkindsofparameterswearereceiving.Inthissimplestofcases,wearenotdealingwithparameters,butwewillinamoment.Theresponseobjectenablesustosettheproperstreamtowhichwecanwriteourdynamicdocument.publicclassGetBrowserDataServletextendsHTTPServlet{publicvoiddoGet(HttpServletRequestrqst,HttpServletResponseresp)throwsServletException,IOException{}}SettingHeadersandDefiningContentOnceweimplementtheservicefunction,wecanfillinthedetails.Wemustsetourresponseparametersfirst.InorderfortheWebservertopassbackadynamicdocument,weneedtotellitwhatkindofdocumentwearesendingback.IsthisaQuicktimemovieoranHTMLfile?Inbrowserparlance,theContentTypefieldoftheresponseheaderspecifiesthetypeoffile;thisisusuallythefilesMIMEtype.IfyouweretostartNetscapeorInternetExplorerandplayaroundwiththesettings,youcouldfarmoffcontenttypestodifferenthelperapplications.Forexample,all.movQuicktimefilessenttoaparticularbrowsercouldendupstartingaQuicktimeMoviePlayerandstarttheanimation.Inmuchthesameway,weneedtospecifywhatkindofdocumentwearesendingbackbysettingthecontenttype.ThisisdonebyusingthesetContentTypemethodoftheHttpServletResponseobject.publicclassGetBrowserDataServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestrqst,HttpServletResponseresp)throwsServletException,IOException{//setuptheresponseresp.setContentType("text/html");}}CreatingtheDocumentNow,weneedastandardoutputstreamtowhichwecanwriteourdynamicdocument.Aswediscussedinthefirstchapter,streamsarewonderfulthingsthathavenumerouspurposes.Herewetakearegularresponseobjectandobtainanoutputstreamforit:publicclassGetBrowserDataServletextendsHttpServlet {publicvoiddoGet(HttpServletRequestrqst,HttpServletResponseresp)throwsServletException,IOException{//setuptheresponseresp.setContentType("text/html");//getthedynamicdocument'soutputstreamServletOutputStreamout=resp.getOutputStream();}}Inordertosendinformationbacktotheclient,wemustcreateanHtmlPageobjectthatwillhandlemuchofourHTMLformatting.Now,wecangenerateourdynamicdocumentsimplybywritingHTMLstringstotheoutputstreamwejustdefined.Ineffect,thissendsthedatawewritedirectlybacktotheclientbrowserviatheWebserver.publicclassGetBrowserDataServletextendsHttpServlet{publicvoiddoGet(HttpServletRequestrqst,HttpServletResponseresp)throwsServletException,IOException{//setuptheresponseresp.setContentType("text/html");//getthedynamicdocument'soutputstreamServletOutputStreamout=resp.getOutputStream();//getthedatafortheHTMLpageStringbrowserAddr=rqst.getRemoteAddr();StringuserAgent=rqst.getHeader("user-agent");If(userAgent==null)userAgent="Unknownbrowser";Stringmethod=rqst.getMethod();Stringpath=rqst.getServletPath();Stringserver=rqst.getServerName();Intport=rqst.getServerPort();//buildtheHTMLout.println("RemoteUserInformation"+""+"

RemoteIPAddress:"+browserAddr+"
RemoteBrowser:"+userAgent+"
RequestMethod:"+method+"
Servlet:"+path+"
Server:"+server+"
HTTPPort:"+port);out.println("");}}ThefollowingisthestaticHTMLproducedbytheGetBrowserDataServletafterIdidaSaveAsinmybrowser.Idoctoreditupalittlebitinmyfavoritetexteditor.The reasonthatIneededtodoctoritupwastoputinsomelinefeedsoitwouldbeviewable.Ifyounotice,inthecodetherearenocarriagereturnsinthestreamofdatathatgoestotheoutputstream.Thebrowser'slayoutenginereceivesthiscontinuousstreamofcharactersandformatsitaccordingtoHTMLlayoutrules;rememberthatcarriagereturncharactersarejustonemorecharacterthathastobeparsedandthendiscarded.RemoteUserInformation

RemoteIPAddress:127.0.0.1
RemoteBrowser:Mozilla/4.5[en](Win98;U)
RequestMethod:GET
Servlet:/servlet/GetBrowserDataServlet
Server:localhost
HTTPPort:8080ThisHTML,afterlayingoutbythebrowser,producedthelayoutshowninFigure7-5.Figure7-5.GetBrowserDataServletoutput.NowaFewWordsonServletTestingandDeploymentWebserversareprettyamazingcreatures;thepeoplewhocreateandnurturethesesoftwareentitiesfillthemwithfeaturesthatmakethemveryusefulandaboveallasfastaspossible.Weallknowthatourbrowsersusecachingtechniquestohelpperformance;theywillnotgobacktotheserverifapageiscachedinthelocalstore.Tohelpservletperformance,Webserverscacheservletssothattheyarealwaysreadilyavailableinmemoryifneeded.Thisisaniceperformancefeatureand,coupledwithahighperformanceJavaVirtualMachine,reallyhelpsmakeservletsasfastaspossible.Nowcomesthehitch;becauseservletsarecachedassoonastheyareloaded,testingbecomescomplicated.Assoonaswecompileanewversionofourservletandwanttotestit,wemustfirstcopyittotheWebserver's"magic"/servlet/ directoryandthenclickonthereloadbuttonofourbrowser.Loandbehold,theoldversionoftheservletisrun.Totestthenewversionoftheservlet,wemustgettheWebserveradministratorto"cycle"(turnoff,thenon)theWebservertoclearthecachesothatitwillloadthenewversionoftheservlet.Doingthisfrequentlycanmakearealenemyofyournormallymild-manneredWebserveradministrator.Inaproductionenvironment,wewanttomakesurethatservletsareextensivelytestedbeforetheyareputintoproduction,sothatonceputintoproductiononlyonecyclingoftheWebserverisnecessary.Entertheservletrunner,apieceofsoftwarethatisdistributedaspartofSun'sJavaServletDevelopmentKit(JSDK).TheservletrunnerallowsyoutotestservletsonyourownWindows-basedworkstation.Servletrunnerisaspecial-purposeWebserverthatyoucanconfigureandrunonyourownworkstation.Youwillstillhavetogothroughthehassleofhavingtostopservletrunnertoclearthecachetotestyournewversionofaservlet,butthatispreferabletoalienatingtheWebadministrationstaff.ServletsandHTMLFormsProcessingThebiggestuseofservletstodayisinthedynamiccreationofHTML-basedformsandprocessingthedatareturnedbyaclientbrowsertotheWebserverfromtheform.BeingJavaprogrammers,weareallfamiliarwithbuildinguserinterfacesusingAWTandSwingtocreateappletsfordeliverytoaWebbrowser.PlainoldHTMLprovidesuswithamuchthinnerclientthatcanbecreatedveryquicklybyaservletandsenttotheclientbrowsermuchmorequicklythananequivalentJavaapplet.(Ihatetosayit,becauseIreallylikethestatefulbehaviorofanapplet,buthavingtowaitfortheclassloadertodoallofitssecuritycheckswhiletheappletisloadingreallymakesmedreadthe"Appletstarting"messageonthebrowser'smessageline.)HTML'sdataentrywidgets(tags)provideasetofdataentryobjectssufficientformostdataentryapplications.Let'sreviewtheHTMLsetofdataentryobjects.FormTag.TosenddatafromaformtotheWebserverrequiresaminimumofasingle

tagset.Webpagesmaycontainmultipleforms,eachbeinglogicallyindependentoftheother....The
taghasnoassociatedlayoutimplicationsforthebrowser;itsonlyimplicationsareprocessingoriented.Thenameattributeoftheformcanbeanythingwewishaslongasitcontainsnoembeddedblanksandisuniquetothisparticularform(withinthecurrentWebpage).ThemethodattributeofthetagisusedtoindicatetothebrowserhowdatafromtheformistobesenttotheWebserver.Therearetwopossiblechoices:GETorPOST.GETinstructsthebrowsertouseanHTTPGEToranHTTPPOSTrequestheader.A GETwillattachallthedatafromtheformtotheURLsenttotheserver(thiswillbeavailabletoyourservletviathegetQueryStringorgetParameterValuesmethod).SettingthemethodattributetoPOSTinstructsthebrowsertosendthedataaspartoftherequestheaderwhereitwillbemadeavailabletotheservleteitherbyreadingtheServletInputStreamorviathegetParameterValuesmethod.DependingonyourchoiceoftheGETorPOSTmethod,yourservletwillhavetooverloadthedoGetordoPostmethodoftheHTTPServletbaseclass.IntheGetBrowserDataServlet,theexecutionoftheservletwaskickedoffbytheimpliedHTTPGetofjustrequestingtheservlet'sURL;thisiswhyweoverloadedthedoGetmethodintheservlet.InputTagThetagisamultipurposetagandisreallyquiteversatile.We'lllookateachofthevariationsofthetagindividually.AsaTextInputorPasswordFieldname—assignsanametothefieldtype—providestextforatextinputfieldpasswordforapasswordfieldsize—indicatesthewidth(characters)ofthedisplayedwidgetmaxlength—indicatesthemaximumnumbersofcharacterstobetypedinvalue—providestheinitialvaluetodisplayinthefieldTextinputfieldsaretheworkhorsesofthedatainputwidgetsandareusedforcollectingbothtextualandnumericdata.Theonlydifferentiationbetweentext,numeric,date,…,informationisthecontextinwhichitisused.EnforcementofdatatypecheckingislefttotheusereitherbyincludingJavascriptdatatypecheckingfunctionsintheWebpageorbyhavingthedata-handlingservletcheckthedataforcorrectnessandposterrormessagesbacktothebrowserasspecialWebpages.ThegeneralfeelingisthatincludingJavascripttodothisispreferabletohavingtheservletdothecheckingasitlocalizesthecheckingtotheclient,placesnoextraprocessingloadontheWebserver,andcutsdownservletsize.Passwordfieldsarethesameastextinputfieldsexceptthat,whentypedinto,thetypedcharacterswilldisplayas*characters;whensubmitted,thename/valuepairwillcontainthetextasitwastyped.AsaCheckBox Checkboxesarelittlesquareboxesthat,whenclickedon,displayasmallcheckmark.Ifaboxisalreadychecked,clickingwillremovethecheckmark.Checkboxesareconvenientforallowingausertochooseasetofoptions.name—aformuniquenameforthefieldtype—mustbecheckboxvalue—avaluetobesenttotheserveriftheboxischecked(Aname/valuepairwillonlybesentistheboxischeckedwhensubmitted.)checked—ifpresent,indicatestodisplaytheboxasinitiallycheckedAsaRadioButtonRadiobuttonsareametaphorfortheone-of-manykindofselectiondevicewehaveonautomobileradios.Whenyoupressone,itcancelsoutanypreviouslyselectedchoice.name—aformuniquenameforagroupofradiobuttonstype—mustberadiovalue—thevalueassociatedwiththisbutton(Thisvaluewillbesenttotheserverwiththename/valuepairifitisselectedatsubmittime.)checked—displaythisbuttonasinitiallyselectedThiswidgetallowsyoutohavemultiplewidgetswiththesamename.Thisallowsgroupingbuttonsintooneofndevices.Forexample,Chevrolet
BMW
Subaru
willdisplaythreeradiobuttonsvertically,eachfollowedbythecarbrand.IftheBMWbuttonisselectedandtheformissubmitted,thename/valuepairtobesenttotheserverwillbecar=BMW.Figure7-6illustratesusesofthetag. Figure7-6.Sampleradiobuttonsandcheckboxes.AsaSubmitButtonSubmitbuttonsarethewidgetthatinitiatesthetransferofdatafromaformtotheWebserver.name—thenameofthisbutton;ifnotincluded,thedefaulttextwillbe"SubmitQuery"type—mustbesubmitvalue—thetexttobedisplayedonthebuttonfaceandsenttotheserverasthevalueofthename/valuepairwhenclickedonAformmayhavemanysubmitbuttonsallwiththesamename;onlythename/valueassociatedwiththeclickedbuttonwillbesenttotheserver.Thisgivesusaconvenientmechanismtousetodecodewhichbuttonwasusedasthesubmitbutton.Ifasubmitbuttonhasnonameorvalueassociatedwithit,noname/valuepairwillbesenttotheserver.Asubmitactionwilltakeplace.AsaResetButtonResetbuttonsareusedtoclearallthedatathathasbeensetinaform.Theresetactionhappenslocallytothebrowserandsendsnothingbacktotheserver.type—mustberesetvalue—thetexttobedisplayedonthebuttonface AsaHiddenFieldHiddenfieldsarenondisplayabletextfieldsandareusedasaconvenientwaytohideprogramstatedata(rememberthatthenatureoftheWebisthatitisstateless)inamannerinwhichitwillnotbeoverlynoticeablebythebrowseruser(unlesstheyusethe"viewsource"capabilityoftheirbrowser).•name—thenameofthisbutton•type—mustbehidden•value—thetexttobesenttotheserverasthevalueofthename/valuepairwhentheformissubmittedAsaFileNameFieldThisfieldisatext-inputfieldwithanassociatedBrowsebutton.ClickingontheBrowsebuttoncausesthesystemFileDialogtobedisplayed.Youcanthenselectafileonyourfilesystembydouble-clickingonthefileorselectingitandclickingontheOpenbutton.Thiswillclosethedialogboxandplacethenameoftheselectedfileinthetextinputportionofthecontrol.Thiswidgetisnotsupportedonallbrowsers.name—thenameofthisbuttontype—mustbefilevalue—thetexttobedisplayedonthebuttonfacewhenafileisselectedfromthefiledialogandsenttotheserverasthevalueofthename/valuepairwhenclickedonsize—sameasfortextinputfieldmaxlength—sameasfortext-inputfieldaccept—acommaseparatedlistofMIMEfiletypestobeusedbythefiledialogtodeterminewhichfiletypedtodisplaySelectTagTheallowsustopresentselectionlistsasadrop-downlist,aone-of-nscrollableselectionbox,oranm-of-nscrollableselectionbox. textname—thenameofthislistsize—numberofvisibleoptions,ifomitteddefaultisonemultiple—ifpresent,thelistwillbemofn;otherwise,oneofnvalue—thevaluesubmittedforthename/valuepairforoneofn;multiplenamevaluepairswillbesubmittedform-of-nlistsselected—ifpresent,indicatespreselectedvalue(s)SeeFigure7-7foranexampleofthetagsetisusedtogiveourformamultilinetext-inputarea.Initialtextdatacanbesuppliedtothefieldbyplacingitbetweentheopening.name—thenameofthislistcols—width,incharacters,oftheinputarearows—height,incharacters,oftheinputarea wrap=virtual—ifpresent,willenabletextwrappingattherightborder;ifabsent,areturnkeyisrequiredtomovethecursortothenextlineThefollowingHTMLproducesthetextareainFigure7-8:Figure7-8.Asampletextarea.Cars

Textarea:
Nowisthetimeforallgoodstudentstocometocometotheaidoftheirteachers

Thatprettymuchtakescareofour5-minuteHTMLrefreshercourse.AllwehavelefttounderstandishowtheinformationisreadfromthescreenandsomethingcalledURL-encoding.ReadingtheFormScreenWhenauserclicksonasubmitbuttonthebrowserbuildsalistofname/valuepairs,theorderingofwhichisdeterminedbytheplacementofthefieldsonthescreen.Scanningisdoneleft-to-rightandtop-to-bottom;whateverisfoundinthatpathisplacedinthelistintheorderitisfound.URL-encodingisaschemedevisedforattachingparameterliststoURLs.ThelastcharacterofaURListhefirstblankcharacterencounteredafterthebeginningoftheURL.ToensurethatallformsdataissenttotheWebserver,wemustmakesurethattherearenoblank(space)charactersinthedata.Todothis,thebrowserdoessomecharactersubstitutionsasitbuildsthelistofname/valuepairs.Spacesarereplacedwith`+'characters,andanyspecialcharacterslikepunctuationarereplacedbya`%'characterfollowedbythehexadecimalvalueofthecharacterintheASCIIcodeset.Finallytheampersandcharacter(`&')isusedtoseparatenamevaluepairs.AServletVersionoftheFeaturedApp Aswehavedoneinpreviouschapters,wewillre-examineourfeaturedAppointmentCalendarapplication.Indoingso,wewillborrowafewprogrammingtechniquesfromCGIprogrammingandapplywhatwe'vealreadylearnedaboutservletprogramming.BecauseourAppointmentCalendarwillnowhaveaverythinclientpresentedtotheenduserthatwillbepurelyHTML,thereislittlethatwecanreusefromtheclientinterfacethatwedevelopedfortheotherchapters.Wehavedoneprettywellonreusesofar;ineachimplementation,wehaveonlyhadtomodifytheNetworkModule.javafileandwriteanewserver(exceptinthecaseoftheJDBCimplementation).Inlookingatwhatwemightconsiderreusing,wecaneasilyreusetheAppointmentTypeclassbecauseitisprettystraightforward.InexaminingtheNetworkModulefortheJDBCversion,wenoticethatwecanuseitasourserver-sideinterfacetotheaccessdatabasewecreated.Figure7-9showstheuserinterfacefortheCalendarandtheappointmentformswehavedecidedtouse.Noticethatwehavemadethetimemoregranularsoastobemorerealistic.Figure7-9.Appointmentcalendaruserinterfaces.Beforewegotoomuchfarther,let'slookatwhattheoverallarchitectureofourservletwillbe.Ourservletwillbemadeupoffourmethods:doGet,getAppointments,newAppointmentForm,andinsertNewAppointment.doGetisourrequiredoverloadofthedoGetmethodoftheHttpServletbaseclass.WechoseGETinsteadofPOSTasourformssubmissionmethodsothatyoucouldseetheURL-encodingoftheformsdatainthelocationboxofyourbrowser.NormallywewoulduseaPOSTsothattheusercouldn'tseethesubmittedURL.ThefunctionofdoGetistoactlikeatrafficcopandanalyzetheinputfromthesubmittedURLanddecideifitisto: 1.DisplaytheappointmentlistbyinvokinggetAppointments,whichinturnusesthegetAppointmentsmethodofourpreviouslywrittenNetworkModule.(That'sanicelittlebitofreuse.)2.DisplaytheaddanemptyappointmentformbyinvokingthenewAppointmentFormmethod.3.InsertanewappointmentintothedatabasebyinvokinginsertNewAppointmentmethod,whichinturnusesthescheduleAppointmentmethodofaNetworkModuleobject.ItlookslikeFigure7-10.Figure7-10.CalendarServlet.We'llstartoutwithaskeletonviewofourapplication'sarchitecture:PublicclassCalendarServletextendHttpServlet{PublicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)ThrowsServletException,IOException{}publicvoidgetAppointments()throwsIOException{}publicvoidnewAppointmentForm()throwsIOException{}publicvoidinsertNewAppointment()throwsIOException{ }}Lookingateachofthemethodsindividually,wecananalyzewhatistakingplaceonethingatatime.Theentirelistingfortheservletwillappearattheendofthissection.doGet()publicvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{Stringvalues[];out=resp.getOutputStream();//addstandardHTMLheaderresp.setContentType("text/html");out.println("Calendar");out.println("");//ifquerystringisnullthisistheinitialcallStrings=req.getQueryString();if(s==null){this.getAppointments();}else{//notinitialcalldecodethesubmitbuttonvalueStringsubmit="";values=req.getParameterValues("submit");if(values!=null)submit=values[0];//checkforaddanappointmentif(submit.equals("AddAppointment"))this.newAppointmentForm();//checkfordisplayappointmentformrequestelseif(submit.equals("Calendar"))this.getAppointments();//checkforinsertanewappointmentelseif(submit.equals("Insert")){//gettheapptdataandaddittothedatabaseStringreason="";inttime=0;values=req.getParameterValues("reason");if(values!=null)reason=values[0];values=req.getParameterValues("time");if(values!=null)time=Integer.parseInt(values[0]);//goinsertthedatathis.insertNewAppointment(reason,time);}}//standardtrailerout.println("");} Thefirstfewlinesofcodejustreserveastringarrayforparameterhandling,attachanOutputStreamtoourgloballydefinedServletOutputStream,andusethestreamtowriteastandardHTMLprologtotheclient.TheoutermostifstatementcheckstheQueryStringfornull;thisisanoldCGItrickusedtodetermineifthisistheinitialinvocationofascript.IfweinvokedourservletfromananchortagonanotherHTMLpagelike:AppointmentCalendarThesubmittedURL,whenclickedon,wouldbe:http://someserver.com/servlet/CalendatServletSubmittingthisURLwillinvoketheservlet,buttheQueryStringwillbeemptybecausethereisnoparametricdataattachedtotheURL.InthiscasedoGetpassescontroltothegetAppointmentsmethodtofinishbuildingtheform.Atthispointtheservletisdone.Ifthisisn'tthefirstinvocation,thentheremusthavebeensomeparametricinformation(name/valuepairs).Becauseallourformshaveatleastonesubmitkey,allwehavetodotodecidewhattodonextisdecodethevalueofthesubmitkey.Ifthekeywasthesubmitkeyforinsertinganewappointmentintothedatabase,therewillbeadditionalparametricinformationintheQueryStringsoweretrieveitandpassittotheinsertNewAppointmentmethod.getAppointments()publicvoidgetAppointments()throwsIOException{try{AppointmentTypeappt=newAppointmentType();Vectorv=newVector();out.println("

Appointment
Calendar

");out.println("

");//createaNetworkModuleobjecttotalktodatabaseNetworkModulenm=newNetworkModule();v=nm.getAppointments();inttemp=0;Stringampm="";for(inti=0;i12){temp=appt.time-12;ampm="PM";}else{temp=appt.time;ampm="AM";}out.println("

");}catch(IOExceptione){System.out.println("IOException:"+e.toString());}}ThegetAppointmentsmethodfirstcreatesanAppointmentTypeobject(reusehere…)toholdtheappointmentsretrievedfromthedatabaseandavectortoholdtheAppointmentTypeobjectsreturnedfromthedatabasebytheNetworkModule.WethencreateaNetworkModuleobjectandinvokeitsgetAppointmentsmethod;thisplacestheappointmentsintothevectorwecreatedpreviously.TheforloopiteratesthroughthevectorandformatseachAppointmentTypeobjectintothe

AddanAppointment

");out.println("");out.println("");out.println("");out.println(""+"");out.println(""+"");out.println("
");out.println("08:00AM");out.println("
09:00AM");out.println("
10:00AM");out.println("
11:00AM");out.println("
12:00Noon");out.println("
");out.println("01:00PM");out.println("
02:00PM");out.println("
03:00PM");out.println("
04:00PM");out.println("
05:00PM");out.println("
");}ThismethodisprettystraightforwardandjustusestheServletOutputStreamtobuildtheempty"addanewappointment"page.IfweweretoaddaModifyExistingAppointmentbuttontotheAppointmentsmainscreen,wecouldmodifythismethodeithertodisplayanemptyscreenforaddinganewappointmentortodisplaythefield,filledinwiththeparsedinformationfromthemainappointmentselectionlist.insertNewAppointment()publicvoidinsertNewAppointment(Stringreason,inttime)throwsIOException{//createaNetworkModuleobjecttotalktothedatabaseNetworkModulenm=newNetworkModule();//addtheappointmentnm.scheduleAppointment(reason,time);redisplaytheAppointmentlistthis.getAppointments();}FinallytheinsertNewAppoinmentmethodcreatesaNetworkModuleobjecttotalktothedatabaseandinvokestheNetworkModule'sscheduleAppointmentmethodtoplacetheappointmentinformationintothedatabase;oncesafeinthedatabase,thegetAppointmentsmethodisinvokedtoredisplaythemainform.Youcannowseetheappointmentthatwasjustadded.JavaServerPagesArecentadditiontoourtoolboxofWebapplicationdevelopmenttoolsareJavaServerPages.ToexplainwhataJSPis,thinkaboutwhatitwasthatweactuallydidwithservlets;simplyput,wewroteaJavaapplicationthat,asitsoutput,created(onthefly)HTMLwithembeddeddatathatwerereturnedtotherequestingbrowser.ThisisveryCGI-likeand,asnaturalasthisfelt10yearsago,isnotaverynaturalwaytocreatedynamicWebpages.Ourotherserver-sidetechnologieslikeMicrosoft'sASP,Allaire'sColdFusion,andPHPtaketheapproachofdevelopinganHTMLpageandthenaddingscriptinginstructionstotheHTMLtogivethepageadynamicnature.Let'sexamine,verybriefly,thesetechnologiesandthenlookatJSP.Now,rememberthattheseareallserver-sidetechnologies. MicrosoftActiveServerPages(ASP)InthecaseofASP,youincludeaveryVisualBasic–likescriptinglanguagethatallowsdatabaseinteractionviaODBCandinteractionwithotherWindowsAPIs,inlinewithyourHTMLcode.Thefilesaretypedas.aspfilesratherthan.html.TheWebserverissetuptoautomaticallyprocess.aspfilesdifferentlythan.htmlfiles;the.aspfiletypecausestheIISWebServertoprocess(resolve)theembeddedscriptingtostaticHTMLwithembeddeddata.ThiscapabilityisbuiltintotheIISWebServerandcomeswithNTServer.PHPPHPtakesthesameapproach(i.e.,anembedded[uniquetoPHP]scriptinglanguagethatisresolvedbyaWebserverplug-inthatisinstalledseparatelyfromtheWebserveritself).PHPisfreelydownloadablefromthePHPWebsiteand,duetoitsprice,isverypopularwithmanysmallerISPs;itisalsopopularwithmanyISPsasitrunsonLINUX,whichisalsopopularwithISPs.AllaireColdFusionColdFusiontakesaslightlydifferentapproachinthatithascreatedasetofwhatlookslikeadditionalHTMLtagsandusesaWebserverplug-intoresolvethe.cfmfilesintoplainoldHTMLtobedeliveredtothebrowser.Theplug-inisnotaCGIbutanactualserverthatrunsalongsideofyourWebserver.ColdFusioniscurrentlyavailableforbothNTandSolaris(codeportabilityisprettygood,althoughtherearesomeproblems,whichwewon'telaborateonhere).Toallowtheusertoextendthetagset,ColdFusionsupportsa"custom"tagextensibilitythatallowsnewtagstobecreatedinColdFusion,C/C++,orJava.AllairerecentlypurchasedLiveSoftware,whichsellsaserver-sideproductcalledJrun.Jrunisaserver-sideplug-inthatletsyouaddaservletcompliantJVMtoWebserversthateitherdon'timplementtheservletAPIordon'timplementitcompletelyorcorrectly.TheJRunserverisalsocompliantwiththeJSPspecification.OnelastthingaboutJrunisthatitsupportsatechnologycalled,whichwillrunColdFusionapplicationsanywherethatJrunwillrun—almosteverymajorplatform.OntoJSPJavaServerPagesisatechnologythatisstillinactivedevelopment.ThecurrentversionofthereferencereleasebySunisversion1.0andcanbedownloadedfromtheSunJavadeveloper'ssite.JavaServerPagesstartsoutasanHTMLpage.Thisletsusstartoutaprojectwithasetofprototypesthataremadeentirelyusingahigh-productivityHTMLGUIinterfacetoollikeMacroMedia'sDreamweaver.Oncewe'veusedtheprototypestosellmanagementoracustomerontheproject,wecangoandturnthosestaticpagesintoactivepagesusingJSP.JSPiscurrentlyinitsinitialreleasefromSunMicrosystems.TheJSP1.0approachissimilartoColdFusion'sapproachofusingspecialtags,butthatiswherethesimilarity ends.TothestandardHTMLtagset,JSPaddsahandfulofJSPActiontags(sixtags)including:•DirectivesfortheJSPengine•In-lineexpressionevaluation•Scriptlets(smallin-linescriptsforgluingthingstogetherorsupplyingfunctionalitynotincludedinbasetags).ThismakeaJSPpageacombinationofHTMLandJSPdirectives,scriptlets,andexpressions.JavaServerPagesmustberunonaWebserverthatiscompliantwiththeservletspecification.TheJSPengineissimilarinfunctiontotheColdFusionserverinthatitisaserverrunningalongsideyourWebserver.WhentheWebservergetsarequestforaURLforaJSP(filetype.jsp),therequestgetshandedofftotheJSPengine,whichnowresolves,onthefly,alltheJSPtagsandinformationintoaJavaservletandthenrunstheservlet.Rememberthatonceaservlet-compliantWebserverrunsaservlet,theservletismaintainedincacheforsubsequentuse.Soundsprettyneat;itis.Let'sgoalittlefartherandlookattheJSPcomponents.JSPDirectivesDirectivesareusedtopassinformationonprocessingthepagetotheJSPengine;thisincludesthingslike"included"files,customtaglibrariesavailable,languageforscripting(currentlyv1.0supportsonlyaJava-likescriptinglanguagebutIwouldexpectJavascriptasanoptioninfuturereleases).JSPTagsJSPtagswilldothemajorityofyourJSPprocessing.Thebasetagsetismadeupoffivetags,asshowninTable7-2.ScriptletsandExpressionEvaluationScriptletsaresnippetsofJavacodethatyouuseto"glue"thepartsofyourJSPtogether.Table7-2.JSPTagsTagUsejsp:useBeanDeclarestheusageofaJavaBeancomponentjsp:setPropertySetsapropertyofaBeanjsp:getPropertyRetrievesaBeanpropertyjsp:includeReplacesthistagwiththecontentsofthespecifiedfilejsp:forwardForwardsaclientrequesttoanotherjsp,anHTMLpage,oraservletToincludeascriptletinyourJSP,placetheJavacodeinsideasetofscriptletdelimiters.Use<%…%>toidentifythebeginningandendofyourscriptlet. Toevaluateanin-lineexpressionandhaveitsresultplacedinlinewithyourHTML,placetheexpressioninside<%=…%>.Essentiallytheresultreplacesthe<%=exp%>.NOTEExpressionevaluationtags(<%=…%>)cannotbenestedinsideascriptlet(<%…%>).Thescriptletmustbeterminated(asshown).Inalikemanner,HTMLtagscannotbenestedinsideascriptlet;thescriptletmustbeterminated(asshown).ThefollowingexcerptfromthefeaturedAppointmentCalendarillustratestheuseofbothofthese.Thissectionofcodeincludestwoscriptlets,anHTML
当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭