A web service presents itself as a web application with the difference that a web service is employed or used by a computer program and not by an individual.
There are many examples of web services, all very specialized : such as currency conversion, meteorology, etc. For example, when you listen to a music CD with Windows Media-Player, the media-player downloads the album name and titles from the internet : in fact it interrogates a web service.
Web services are increasingly being used to integrate programs in a group of applications : called interoperability between applications.
Several customers have already asked us to extend and automate import / export functions of HYPERPLANNING to exchange data with other programs. It quickly becomes apparent that importing / exporting in a file is not flexible enough to exchange complex data. HYPERPLANNING Web Service addresses this shortfall.
It is not necessary to be an application developer to write a script or a program using a web service, it is just necessary to know the basics of programming such as
You can just write a script (PowerShell, Python, etc.) or use a programming environment (Java, .net, C++, Pascal, etc.) according to your needs and your programming level. Your program runs on the platform of your choice (the server is only available on MS-Windows, see below).
We have chosen to rely on standards for the implementation of HYPERPLANNING Web Service : the service is described by a WSDL document and communicates with applications using the SOAP protocol over an HTTP (or HTTPS) connection. All recent programming languages incorporate what is needed to interrogate a server of this type without prior knowledge of WSDL, SOAP or HTTP, and there are extensions that perform on almost all older languages.
HYPERPLANNING Web Service is designed to operate under :
Windows Server versions are recommended because they do not limit the number of simultaneous connections.
For HYPERPLANNING Server, HYPERPLANNING Web Service is seen as HYPERPLANNING Client (with the counting of the licenses).
HYPERPLANNING Web Service uses a connection license, HYPERPLANNING.net : every HYPERPLANNING.net license allows you simultaneously run HYPERPLANNING Web Service and HYPERPLANNING.net for each server.
Choose a schedule, add a publication (right-click, Create a new publication) and release this publication.
Click on Publication parameters to specify the different parameters and reserve the URL prefix. This reservation requires knowing the workstation's Windows administrator account.
If you choose the HTTPS protocol, you must also create a link with a certificate. This can be done at the same time as creating the reservation or later from the menu Assistance, Administration of Windows parameters.
Click on Start the web service to start the publication then on the button Open in a browser : the presentation page must appear. This page gives access to the WSDL document in several forms, see below.
If your browser is recent, the WSDL document is displayed in tree form, making it easier to read the document.
A web service usually exposes a single WSDL document to describe the operations it can handle. However some types of clients of the web service have their own limitations while others do not and it would be regretful to degrade, for all types of clients, a WSDL document rich in information to a poorer document because a such and such type of client does not know how to process it.
Thus we have chosen to expose three complete WSDL documents, each being declined in as many partial WSDL as there are interfaces.
<xsd:simpleType name="THpSvcWCleMatiere">These declarations of an alias are removed from the WSDL document and the base type is used everywhere instead of the alias.
<xsd:restriction base="xsd:unsignedInt" />
</xsd:simpleType>
The advanced programming languages all offer to import the WSDL document once and for all, allowing quick access to the web service.
On the other hand, the less advanced languages and scripting languages load the WSDL document at every launching. Access to the web service is very slow.
For these languages we exhibit a WSDL document per interface (port type) and per type of WSDL document.
Thus a script manipulating only the interface IHpSvcWEtudiants can it load the partial WSDL of this interface, this WSDL document is much smaller and access will be all the faster.
The examples listed here require version 3.0 or higher of the Microsoft .net platform.
From the version 3.0 of the Microsoft .net platform the HTTP Basic authentication is no longer managed for HTTP (only for HTTPS). To bypass this limitation we will build an assembly HpSvcW.Authentification.dll that defines the class AuthentificationHpSvcW that handles everything.
Start by saving the following file under the name HpSvcW.Authentification.cs :
using System; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.Text; namespace HpSvcW.Authentification { // Class that can add the HTTP header for HTTP Basic authentication of // HYPERPLANNING Web Service public class AuthentificationHpSvcW : IClientMessageInspector, IEndpointBehavior { // Value for the HTTP header Autorization private string m_Authorisation; // Constructor public AuthentificationHpSvcW(string aIdentifiant, string aMotDePasse) { string lAEncoder = aIdentifiant + ":" + aMotDePasse; string lEncode = Convert.ToBase64String(Encoding.ASCII.GetBytes(lAEncoder)); m_Authorisation = "Authorization: Basic " + lEncode; } // Implementation of IClientMessageInspector // Add the HTTP header public object BeforeSendRequest(ref Message request, IClientChannel channel) { // We add the HTTP header HttpRequestMessageProperty lEntetes; object lPropriete; if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out lPropriete) == true) { lEntetes = lPropriete as HttpRequestMessageProperty; } else { lEntetes = new HttpRequestMessageProperty(); request.Properties.Add(HttpRequestMessageProperty.Name, lEntetes); } lEntetes.Headers.Add(m_Authorisation); return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { // Nothing } // Implementation of IEndpointBehavior // Saved as IClientMessageInspector to be called for every query public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { // Nothing } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(this); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { // Nothing } public void Validate(ServiceEndpoint endpoint) { // Nothing } } }
The compiler C# csc.exe is present on your workstation if the Windows development kit (Windows SDK) is installed. It is the case if Visual Studio is installed. It is somewhere under C:\Windows\Microsoft.NET\Framework.
Compile HpSvcW.Authentification.cs like this :
csc.exe /target:library HpSvcW.Authentification.cs
It builds the assembly HpSvcW.Authentification.dll
Under Visual Studio create a new project Fichier / New / Project ... / Application console, Name = TestHpSvcW
Menu Projet / Add a service reference ..., Address = http://myserver/hpsw/wsdl/SansTypeSimple, Namespace = HpSvcW, OK.
Menu Projet / Add a reference .../Browse, choose HpSvcW.Authentification.dll compiled during previous stage.
Then modify Program.cs as follows :
using System; using System.Net; using System.ServiceModel; using System.Text; using HpSvcW.Authentification; using TestHpSvcW.HpSvcW; namespace TestHpSvcW { class Program { static void Main(string[] args) { try { Console.Write("Identifiant : "); string lIndentifiant = Console.ReadLine(); Console.Write("Mot de passe : "); string lMotDePasse = Console.ReadLine(); AuthentificationHpSvcW lAuthentification = new AuthentificationHpSvcW(lIndentifiant, lMotDePasse); // Used interfaces HpSvcWAdminClient lAdmin = new HpSvcWAdminClient(); lAdmin.Endpoint.Behaviors.Add(lAuthentification); HpSvcWMatieresClient lMatieres = new HpSvcWMatieresClient(); lMatieres.Endpoint.Behaviors.Add(lAuthentification); //Display of the version Console.WriteLine("Connecté à " + lAdmin.Version()); // Display of the number of subjects Console.WriteLine("Il y a {0:D} matières dans la base", lMatieres.NombreMatieres()); // Display of the list of subjects THpSvcWTableauClesMatieres lCles = lMatieres.ToutesLesMatieres(); lCles = lMatieres.TrierTableauDeMatieresParLibelleEtCode(lCles); THpSvcWTableauChaines lCodes = lMatieres.CodesTableauDeMatieres(lCles); THpSvcWTableauChaines lLibelles = lMatieres.LibellesTableauDeMatieres(lCles); THpSvcWTableauChaines lLibellesLongs = lMatieres.LibellesLongsTableauDeMatieres(lCles); for (int lIndice = 0; lIndice < lCles.Count; lIndice++) Console.WriteLine("{0,3:D} {1,-8} {2,-20} {3}", lCles[lIndice], lCodes[lIndice], lLibelles[lIndice], lLibellesLongs[lIndice]); } catch (Exception lException) { Console.WriteLine("ÉCHEC : " + lException.Message); } } } }
You can now generate the solution and execute it on the command line.
# Stop the execution at the first error $ErrorActionPreference="stop"; [String]$lPrefixeWsdl='http://monserveur/hpsw/wsdl/SansTypeSimple'; # Authentication window $lIdentification = Get-Credential; # Used interfaces $lAdmin = New-WebServiceProxy -uri "$lPrefixeWsdl/IHpSvcWAdmin" -Credential $lIdentification; $lMatieres = New-WebServiceProxy -uri "$lPrefixeWsdl/IHpSvcWMatieres" -Credential $lIdentification; # Display of the version "Connecté à " + $lAdmin.Version(); # Display of the number of subjects "Il y a {0:D} matières dans la base" -f $lMatieres.NombreMatieres(); # Display of the list of subjects $lCles = $lMatieres.ToutesLesMatieres(); $lCles = $lMatieres.TrierTableauDeMatieresParLibelleEtCode($lCles); $lCodes = $lMatieres.CodesTableauDeMatieres($lCles); $lLibelles = $lMatieres.LibellesTableauDeMatieres($lCles); $lLibellesLongs = $lMatieres.LibellesLongsTableauDeMatieres($lCles); for ($lIndice = 0; $lIndice -lt $lCles.Count; $lIndice++) {"{0,3:D} {1,-8} {2,-20} {3}" -f $lCles[$lIndice], $lCodes[$lIndice], $lLibelles[$lIndice], $lLibellesLongs[$lIndice]};
You can execute these commands one by one on the PowerShell command line or save them in a file TestHpSvcW.ps1 that you can execute like this :
.\TestHpSvcW.ps1
on the PowerShell command line or like this :
PowerShell .\TestHpSvcW.ps1
in a batch file or on the MsDos command line.
You may first need to execute the command
Set-ExecutionPolicy RemoteSigned
on the PowerShell command line.
This example is based on the development environment NetBeans but any other Java development environment can work.
Create a new Java application
Now modify Main.java like this
package testhpsvcw; import com.indexeducation.frahtm.hpsvcw.*; import java.util.List; import javax.xml.ws.BindingProvider; public class Main { public static void main(String[] args) { try { java.io.DataInput lEntrees = new java.io.DataInputStream(System.in); System.out.print("Identifiant : "); String lIdentifiant = lEntrees.readLine(); System.out.print("Mot de passe : "); String lMotDePasse = lEntrees.readLine(); // Used services HpSvcWAdmin lServiceAdmin = new HpSvcWAdmin (); HpSvcWDonnees lServiceDonnees = new HpSvcWDonnees (); // Used interfaces IHpSvcWAdmin lAdmin = lServiceAdmin.getPortAdmin(); ((BindingProvider)lAdmin).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, lIdentifiant); ((BindingProvider)lAdmin).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, lMotDePasse); IHpSvcWMatieres lMatieres = lServiceDonnees.getPortMatieres(); ((BindingProvider)lMatieres).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, lIdentifiant); ((BindingProvider)lMatieres).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, lMotDePasse); //Display of the version System.out.println("Connecté à " + lAdmin.version()); // Display of the number of subjects System.out.println(String.format("Il y a %d matières dans la base", lMatieres.nombreMatieres())); // Display of the list of subjects THpSvcWTableauClesMatieres lCles = lMatieres.toutesLesMatieres(); lCles = lMatieres.trierTableauDeMatieresParLibelleEtCode(lCles); THpSvcWTableauChaines lCodes = lMatieres.codesTableauDeMatieres(lCles); THpSvcWTableauChaines lLibelles = lMatieres.libellesTableauDeMatieres(lCles); THpSvcWTableauChaines lLibellesLongs = lMatieres.libellesLongsTableauDeMatieres(lCles); List<Long> lListeCles = lCles.getTHpSvcWCleMatiere(); List<String> lListeCodes = lCodes.getString(); List<String> lListeLibelles = lLibelles.getString(); List<String> lListeLibellesLongs = lLibellesLongs.getString(); for (int lIndice = 0; lIndice < lListeCles.size(); lIndice++) System.out.println(String.format("%1$3d %2$-8s %3$-20s %4$s", lListeCles.get(lIndice), lListeCodes.get(lIndice), lListeLibelles.get(lIndice), lListeLibellesLongs.get(lIndice))); } catch(Exception lException) { System.out.println("ÉCHEC : " + lException.getMessage()); } } }
You can now implement the project.
Delphi knows how to generate access code to a web service from its WSDL document :
This generates the Delphi wsdl.pas unit
This unit can also be generated on the command line as follows :
WSDLImp.exe -P -Ou- http://monserveur/hpsw/wsdl
Now create this command line program (TestHpSvcW.dpr) :
program TestHpSvcW; {$APPTYPE CONSOLE} uses Soap.SOAPHTTPClient, // THTTPRIO Soap.SOAPHTTPTrans, // THTTPReqResp System.NetEncoding, // TNetEncoding System.SysUtils, // Exception Winapi.ActiveX, // CoInitialize Winapi.WinInet, // HttpAddRequestHeaders wsdl; // Unit generated by Delphi from the document WSDL (******************************************************************************) type TTestHpSvcW = class (TObject) private fAuthentification : string; // Event allocated to HTTPWebNode.OnBeforePost in CreerRio () // to manage HTTP Basic authentication procedure AjouterAuthentification (const aHTTPWebNode : THTTPReqResp; aHandle : Pointer); function CreerRio () : THTTPRIO; public constructor create (const aIdentifiant, aMotDePasse : string); // Create then delete a new subject by giving the number of // subjects before and after every stage procedure CreerMatiereHyperPlanning (); // Interrogate HYPERPLANNING to recover the list of subjects procedure ListerLesMatieresHyperPlanning (); end; (******************************************************************************) procedure TTestHpSvcW.AjouterAuthentification (const aHTTPWebNode : THTTPReqResp; aHandle : Pointer); begin if not HttpAddRequestHeaders (aHandle, PChar (fAuthentification), Length (fAuthentification), HTTP_ADDREQ_FLAG_ADD) then Assert (False, 'Échec de HttpAddRequestHeaders ()'); end; (******************************************************************************) function TTestHpSvcW.CreerRio () : THTTPRIO; begin Result := THTTPRIO.Create (Nil); Result.HTTPWebNode.OnBeforePost := AjouterAuthentification; end; (******************************************************************************) constructor TTestHpSvcW.create (const aIdentifiant, aMotDePasse : string); var lAEncoder : TBytes; begin inherited Create (); lAEncoder := TEncoding.ANSI.GetBytes (aIdentifiant + ':' + aMotDePasse); fAuthentification := 'Authorization: Basic ' + TNetEncoding.Base64.EncodeBytesToString (lAEncoder); end; (******************************************************************************) procedure TTestHpSvcW.CreerMatiereHyperPlanning (); var lAdmin : IHpSvcWAdmin; lMatieres : IHpSvcWMatieres; lMatiere : THpSvcWCleMatiere; begin // We display the version number of HYPERPLANNING Web Service lAdmin := GetIHpSvcWAdmin (False, '', CreerRio ()); Writeln ('Connecté à ' + lAdmin.Version ()); lMatieres := GetIHpSvcWMatieres (False, '', CreerRio ()); with lMatieres do begin Writeln (Format ('Il y a %d matières dans la base.', [NombreMatieres ()])); LMatiere := CreerMatiere ('Toto', 'TT'); Writeln (Format ('Création réussie : il y a %d matières dans la base.', [NombreMatieres ()])); SupprimerMatiere (LMatiere); Writeln (Format ('Suppression réussie : il y a à nouveau %d matières dans la base.', [NombreMatieres ()])); end; end; (******************************************************************************) procedure TTestHpSvcW.ListerLesMatieresHyperPlanning (); const C_FormatColonnes = '%0:3d %1:-8s %2:-20s %3:s'; var lMatieres : IHpSvcWMatieres; lCles : THpSvcWTableauClesMatieres; lCodes, lLibelles, lLibellesLongs : THpSvcWTableauChaines; lIndice : integer; begin lMatieres := GetIHpSvcWMatieres (False, '', CreerRio ()); with lMatieres do begin lCles := TrierTableauDeMatieresParLibelleEtCode (ToutesLesMatieres ()); lCodes := CodesTableauDeMatieres (lCles); lLibelles := LibellesTableauDeMatieres (lCles); lLibellesLongs := LibellesLongsTableauDeMatieres (lCles); end; for lIndice := low (lCles) to high (lCles) do Writeln (Format (C_FormatColonnes, [lCles [lIndice], lCodes [lIndice], lLibelles [lIndice], lLibellesLongs [lIndice]])); end; (******************************************************************************) (******************************************************************************) procedure MainTestHpSvcW (); var lIdentifiant, lMotDePasse : string; lTest : TTestHpSvcW; begin Write ('Identifiant : '); Readln (lIdentifiant); Write ('Mot de passe : '); Readln (lMotDePasse); lTest := TTestHpSvcW.Create (lIdentifiant, lMotDePasse); try lTest.CreerMatiereHyperPlanning (); lTest.ListerLesMatieresHyperPlanning (); except on lException : Exception do Writeln (lException.Message); end; lTest.Destroy (); end; (******************************************************************************) begin // CoInitialize required for msxmldom.CreateDOMDocument CoInitialize (nil); MainTestHpSvcW (); CoUninitialize (); end.
You can now compile the project and execute it from the command line.
Since version 5, PHP integrates the SOAP extension that allows you to easily create and interrogate a web service.
Verify that the soap extension is enabled in the file php.ini (--enable-soap)
Here is an example of a soap client that allows to query HYPERPLANNING Web Service web :
<?php // URL of the WSDL document of HYPERPLANNING Web Service $WSDL = "http://localhost/hpsw/wsdl/RpcEncoded"; // Connection username and password $LOGIN = "SW"; $PASS = "SWSW"; // Creation of the SOAP client $client = new SoapClient($WSDL, array('login'=> $LOGIN,'password'=> $PASS)); // Display of the number of teachers $NombreEnseignants = $client->NombreEnseignants(); print "<strong>$NombreEnseignants enseignants.</strong><br/>\n"; // Display of the "Surname and First name" of the teachers $Enseignants = $client->TousLesEnseignants(); print "<strong>Nom et Prénom des enseignants :</strong><br/>\n"; foreach ($Enseignants as $Enseignant_ID) { $NomEnseignant = $client->NomEnseignant($Enseignant_ID); $PrenomEnseignant = $client->PrenomEnseignant($Enseignant_ID); print "$NomEnseignant $PrenomEnseignant<br/>\n"; } ?>
Paste this code in the notebook, modify the constants $WSDL, $LOGIN, $PASS and save the file under the name SoapClientPHP.php in your directory root (by default www/). This dierectory is defined by DocumentRoot in the file httpd.conf.
Launch the file from your Internet browser: http://localhost/SoapClientPHP.php
This script displays the number of teachers as well as their surnames and first names
Here is an example of a script in Python that allows the interrogation of HYPERPLANNING Web Service :
from requests import Session from requests.auth import HTTPBasicAuth from zeep import Client from zeep.transports import Transport session = Session() session.auth = HTTPBasicAuth("MyLogin", "MyPassword") lPrefixeWsdl='http://monserveur/hpsw/wsdl/' # Used interfaces Matiere = Client(lPrefixeWsdl + 'IHpSvcWMatieres', transport=Transport(session=session)) Admin = Client(lPrefixeWsdl + 'IHpSvcWAdmin', transport=Transport(session=session)) # Display of the version print ('Connected to ' + Admin.service.Version()); # Display of the number of subjects print ('There are' + str(Matiere.service.NombreMatieres()) + 'subjects in the database'); # Display of the list of the subjects lCles = Matiere.service.TrierTableauDeMatieresParLibelleEtCode ({'THpSvcWCleMatiere' : Matiere.service.ToutesLesMatieres()}); lClesIn = {'THpSvcWCleMatiere' : lCles}; lCodes = Matiere.service.CodesTableauDeMatieres(lClesIn); lLibelles = Matiere.service.LibellesTableauDeMatieres(lClesIn); lLibellesLongs = Matiere.service.LibellesLongsTableauDeMatieres(lClesIn); for i in range (len (lCles)): print (str(lCles[i]) + ' ' + str(lCodes[i] if lCodes[i] is not None else ' ') + ' ' + str(lLibelles[i]) + ' : ' + str(lLibellesLongs[i] if lLibellesLongs[i] is not None else '-'))
To execute this script, paste this code in the notebook, modify 'MyLogin', 'MyPassword', 'http://myserver/hpsw/wsdl/' and save the file under the name ExempleHpSvcW.py :
Open it with IDLE Python and execute (F5) or enter in the DOS command line the command
ExempleHpSvcW.py
In addition to Python 3.6, it is necessary to installer the Zeep module. To install Zeep, enter in a DOS console the command
pip install zeep
This script displays the subjects present in the database
There are good quality commercial and free tools to debug a program using a Web service, however they require a good knowledge of the SOAP protocol to be used.
Some of these tools act as a proxy to analyze traffic between your program and the Web service. That's fine, but be careful, these tools don't always show you everything. For example they can hide the WSDL document request from the server, even return a modified WSDL document, or hide the HTTP headers while they contain the authentication information.
Be aware that if you receive an HTTP 401 error, the username and password have not been sent to the Web service. If you receive an HTTP 403 error, it is because the username and password have been sent to the Web service but they are not those expected.
It is important that the access to the Web service remains protected by a username and password. If your programming language does not manage HTTP authentication "basic" you can specify the username and password in the local WSDL document. Follow these steps :
<soap:address location="http://TT:TTTTTTTT@monserveur/hpsw/Matieres" />
Note for Windows users : Since the update MS04-004 Cumulative Security Update for Internet Explorer (832894), the syntax http://TT:TTTTTTTT@monserveur/hpsw/Matieres is rejected by default. You may need to allow this syntax for a particular program by inserting a key in your workstation's Windows registry.
There was a component under Windows XP called MSSOAP (Microsoft Soap Toolkit) that allowed to invoke Web services from VBA. This no longer exists for the newer versions of Windows.
Now you need to use Visual Studio to produce code that will run in your Microsoft Office documents. Here are a few resources :
WS-I is an organization that proposes another standard called Basic Profile for the web services compared to that of World Wide Web Consortium.
HYPERPLANNING Web Service is not compatible with WS-I for several reasons :
wsi:Claim
, wsi="http://ws-i.org/schemas/conformanceClaim/") in the elements wsdl:documentation even though the latter, such as commentaries, should be ignored by programs. The elements wsdl:documentation provide information for the use of the person writing the program that will use the Web service.