====== How to write a jSeduite Web Service ====== Building a Web Service using the JAx-WS framework is not such a big deal. But, to ensure that the service can be included inside the jSeduite service pool, you **must** follow a set of guidelines and then make jSeduite maintainer's life easier (and it's not such a big deal too LOL ). **''$JSEDUITE_HOME''** refers to the folder where you've //checkout--ed// the SVN repository content. ===== Netbeans Project Creation ===== * Create a new project inside your workspace: * Choose the ''Java Web'' //category//, and then the ''Web Application'' //project// type. * //Name & Location//: * Set the ''Name'' to your service name (without the ''Service'' postfix) * **Be sure** that you're using ''$JSEDUITE_HOME/webservices'' as ''Project Location'' * Tick the ''Use dedicated folder for storing librairies'' box * Click ''Next'' * //Server & Settings//: * Use the **local** GlassFish V2 as ''Server'' * Set the ''Context Path'' to ''/jSeduite/ProjectName'' instead of ''/ProjectName'' * Click ''Finish'' as we're not going to use any built-in framework. ===== Web Service Creation ===== * Right click on you project root, and then choose ''New / Web Service'' * //Name & Location//: * Enter the service name as //Web Service Name// * Use the following scheme to define the ''Package'': ''provider.**jSeduite.technical**.category'' * //eg// use the ''fr.unice.i3s.modalis.jSeduite.technical.image.picasa'' package to represent a service published by ''modalis.i3s.unice.fr'' which deals with ''image'' category and more precisely ''picasa'' concept. * Click ''Finish''. * The Java editor will open the new Web Service class file * Insert the //[[:arch:licence|licence header]]// code before the class declaration If you wan to save a lot of time (and make Netbeans more reactive), deactivate the ''auto-deploy'' silly mechanism: * Right click on the Project root node, and select ''Properties'' * Choose the ''Run'' node in the left panel * Untick the ''Deploy on save'' check box. ===== Interface Creation ===== * Switch the service into //Design// view. * Use the //Add Operation ...// wizard to generate operations skeletons * Really use it to generate skeletons, it saves a lot of time * Customize the skeletons by hand to add more advanced concepts (like array, exotic objects, ...) * After creating all operations, switch to the //Source// view * Check operation signature definition, and fix the code //look// if Java conventions are violated * Comment all operations using the standard javadoc tags Here is an example of such an operation: /** Log an error inside the system * @param trigger Name of the orchestration where the error was catched * @param level log level [eg SEVERE, INFO, WARNING, FATAL, ...) * @param message the content of the error message */ @WebMethod(operationName = "log") @Oneway public void log(@WebParam(name = "trigger") String trigger, @WebParam(name = "level") String level, @WebParam(name = "message") String message) { // Your code goes here ... } ===== Business Object ===== If the web service use a complex data model, this model **must** be defined as a simple Java class as JAX-WS will manipulate simple [[wp>POJO]]. * Right click on the ''Source Packages'' node * Choose your package name, and then right-click and choose ''New / Java Class'' * Include the [[:arch/licence|licence header]] comment * Define the data class: * All attributes are ''private'' * You **must** define a constructor with 0 parameters as JAX use Java intercession capabilities to build POJOs from SOAP messages at runtime. * When an attribute got a //getter// and a //setter// it can be serialized into XML and then exchanged with the //real world//. **Warning**: Be careful on the name you give to your business object class ... * If an exception occurs at deployment time (//Exception occured in the wsgen process javax.xml.ws.WebServiceException: Unable to create JAXBContext//), the XML serialization process fails somewhere. - You forgot to define a constructor with no args - You're using a //weird// name for you class. As each Web service operation is mapped into a ComplexType, you cannot define a Class with the same name as an operation's one. * => You cannot define a ''Log'' data class if you're defining a ''log(...)'' operation. ===== Librairies ===== ==== Database connectivity ==== **Database usage MUST be handled trough the [[:services:libs:databaseconnection]] library.** * Right click on the ''Library'' node. * Choose ''Add Project''. * Go to ''$JSEDUITE_HOME/librairies'' directory * Select the ''DatabaseConnection'' project (java cup) * Be sure that the ''dist/DatabaseConnection.jar'' file is highlighted on the right panel * Click on the ''Add Project Jar Files'' button to create the link. * Add the following ''import'' statement inside your service code: import fr.unice.i3s.modalis.jSeduite.libraries.mysql.*; ==== Third Party ==== * To include //third party// libraries, right click on the //Librairies// node inside the project. * Select the ''Add JAR/ Folder'' menu item. * Go to you library ''jar'' file using the file chooser panel * Tick the ''Copy to Librairies Folder'' radio button * Validate the library using the ''Choose'' button. ===== Database Scheme ===== If the web service use the database as persistent back-end, you'll have to describe the table creation process in a SQL file. * Open the ''$JSEDUITE_HOME/librairies/DatabaseSchemas'' project * Create a ''New SQL File'' using ''ServiceName'' as file name inside the ''Schemas'' folder * The ''.sql'' extension is automatically added * The script **must** use a ''DROP TABLE IS EXISTS'' statement before describing a new relation. * => It helps the bundle deployment process. * If you need to add initial data set, define a ''ServiceName_init'' file inside the ''Data'' package. ===== Collaborative Environment ===== ==== SVN Repository ==== * Right click on the project root node * Choose the ''Subversion'' menu item, and then ''Commit'' * Describe your code in one or two lines * click on the ''Commit'' button ===== Documentation ===== ==== Contract Extraction ==== You'll have to add the WSDL contracts (and its XSD datamodel) into the global contracts repository. * Location: $JSEDUITE_HOME/architecture/contracts To perform such a job, you can use the ''add_contract.sh'' bash script : mosser@asmodeus:~/repositories/jseduite/architecture$ ./add_contract.sh http://localhost:8080/jSeduite/PartnerKeys/PartnerKeysService # Retrieving remote files 20:37:09 URL:http://localhost:8080/jSeduite/PartnerKeys/PartnerKeysService?wsdl [2183/2183] -> "/tmp/add_contract.sh.XXXXXX.gQE41Waa" [1] 20:37:09 URL:http://localhost:8080/jSeduite/PartnerKeys/PartnerKeysService?xsd=1 [1076/1076] -> "/tmp/add_contract.sh.XXXXXX.Z37DPqk6" [1] # Formatting XSD file contracts/PartnerKeysService.xsd: XML document text # Replacing schemaLocation attribute in WSDL file # Formating WSDL file contracts/PartnerKeysService.wsdl: XML document text ==== Architectural Description ==== The jSeduite [[:services:arch:start]] allows formal techniques to be used over the global architecture. Enhance the ''$JSEDUITE_HOME/architecture/description/jSeduite.pl'' description using this tools to take care of your new service. ==== Wiki Description ==== * Create a wiki page inside the '':services:ws'' namespace * Describe your service * You **must** use the [[:services:ws:ws-template| Web Service Description Template]] * Edit the [[:services:ws:start|Web Services index]] page and add a link to your service ==== Official Download creation ==== * Retrieve the service ''jar'' file in the ''$JSEDUITE_HOME/webservices/ServiceName/dist'' folder * Rename it as ''ServiceName-vX.y.war'' (X and y as for the releasing process) * Create a ''New Download'' inside the [[http://code.google.com/p/jseduite/downloads/list|GoogleCode interface]] * Use the following pattern as download name: ''ServiceName X.y Service'' * Add the following tags: ''Type-WebService'' & ''Since-M.n'' where M.n is the current jSeduite release * Click on ''submit file'' to upload the War file. ===== jSeduite Admin Only ===== ==== Releasing Process ==== * Right click on the project root node, and then choose ''Subversion / Copy To'' * Choose the ''Remote folder'' instead of the ''Local'' one. * Choose the ''Repository Location'' using the following scheme: * ''releases/X.y/webservices/ServiceName'' * ''X'' is the major version number * ''y'' is the revision number inside this version. * Enter a message inside the ''Copy Description'': ''Service Name X.y release'' * End by clicking on the ''Copy'' button You cannot //re-copy// a folder into the release one. If you absolutely need to perform a new release with same version number, you'll have to delete the old one before using the following command line: mosser@asmodeus:~/repositories/jSeduite$ svn delete https://jseduite.googlecode.com/svn/releases/X.y/webservices/ServiceName To create a new release folder, use the usual ''svn mkdir'' command from the command line: mosser@asmodeus:~/repositories/jSeduite$ svn mkdir --parents https://jseduite.googlecode.com/svn/releases/X.y/webservices