You are on page 1of 9

Ecole Supérieure Privée Technologies & Ingénierie

Type d’épreuve : Devoir Examen SESSION PRINCIPALE


Enseignant : I. Mouakher
Matière : Architecture Orientée Services
Année Universitaire : 2021-2022 Semestre :1
Classe : CII-2-DMWM
Documents : Autorisés (documents papier uniquement) Non autorisés
Date : 06/01/2022 Durée : 1h30mn
Nombre de pages :2
__________________________________________________________________________________

Exercice 1
1ère Solution : On considère ces deux web services SOAP :
OrderManagementService et CustomerManagementService.
On présente l'interface de ces services par deux classes (voir
figure). Ces deux services gèrent les clients et leurs commandes.
Un client est identifié par un id et a un nom et un prénom. Un
client possède des commandes. Une commande est identifiée
par un id et a une description, un montant et un statut.
1. Donner un WSDL pour le web service CustomerManagementServicve (uniquement
discription abstraite).
<wsdl:definitions
xmlns:wsdl=http://schemas.xmlsoap.org/wsdl/
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.tekup.de/country/ws/Customers"
targetNamespace="http://www.tekup.de/ws/Customers">

<wsdl:types>
<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema
elementFormDefault="qualified"
targetNamespace="http://www.tekup.de/ws/Customers">

<xs:simpleType name="status">
<xs:restriction base="xs:string">
<xs:enumeration value="received"/>
<xs:enumeration value="in_progress"/>
<xs:enumeration value="approved"/>
<xs:enumeration value="complete"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="order">
<xs:sequence>
<xs:element name="id" type="xs:ID"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="amount" type="xs:float"/>
<xs:element name="stat" type="tns:statut"/>
</xs:sequence>
</xs:complexType>
<xsd:complexTypename="orderArray" final="#all">
<xsd:sequence>
<xsd:elementname="item" type="tns:order" minOccurs="0"
maxOccurs="unbounded" nillable="true"/>
</xsd:sequence>
</xsd:complexType>

<xs:complexType name="customer">
<xs:sequence>
<xs:element name="id" type="xs:ID"/>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
<xs:element name="Orders" type= "tns:orderArray"/>
</xs:sequence>
</xs:complexType>

<xsd:complexTypename="customerArray" final="#all">
<xsd:sequence>
<xsd:element name="item" type="tns:customer" minOccurs="0"
maxOccurs="unbounded" nillable="true"/>
</xsd:sequence>
</xsd:complexType>
</xs:schema>

</wsdl:types>

<message name="getCustomersRequest"/>

<message name="getCustomersResponse">
<part name="value" type="tns:customerArray"/>
</message>

<message name="addCustomerRequest">
<part name="value1" type="xs:string"/>
<part name="value2" type="xs:string"/>
</message>
<message name="addCustomerResponse">
<part name="value" type="tns:customer"/>
</message>

<message name="getCustomerDetailsRequest">
<part name="value" type="xsd:ID"/>
</message>
<message name="getCustomerDetailsResponse">
<part name="value" type="tns:customer"/>
</message>

<message name="updateCustomerRequest">
<part name="value1" type="xs:ID"/>
<part name="value2" type="xs:string"/>
<part name="value3" type="xs:string"/>
</message>

<message name="updateCustomerResponse">
<part name="value" type="tns:customer"/>
</message>
<message name="deleteCustomerRequest">
<part name="value" type="xs:ID"/>
</message>
<message name="deleteCustomerResponse">
<part name="value" type="tns:customer"/>
</message>
<wsdl:portType name="CustomerService">
<wsdl:operation name="getCustomers">
<wsdl:input message="tns: getCustomersRequest"></wsdl:input>
<wsdl:output message="tns: getCustomersResponse"></wsdl:output>
</wsdl:operation>

<wsdl:operation name="addCustomer">
<wsdl:input message="tns:addCustomerRequest"></wsdl:input>
<wsdl:output message="tns:addCustomerResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="getCustomerDetails">
<wsdl:input message="tns:getCustomerDetailsRequest"></wsdl:input>
<wsdl:output message="tns:getCustomerDetailsResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="updateCustomer">
<wsdl:input message="tns:updateCustomerRequest"></wsdl:input>
<wsdl:output message="tns:updateCustomerResponse"></wsdl:output>
</wsdl:operation>
<wsdl:operation name="deleteCustomer">
<wsdl:input message="tns:deleteCustomerRequest"></wsdl:input>
<wsdl:output message="tns:deleteCustomerResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
2. Donner un message SOAP pour appeler l’opération getCustomerDetails().
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns=" http://www.tekup.de/ws/Customers">
<soapenv:Header/>

<soapenv:Body>
<tns:getCustomerDetailsRequest >
<value>2</value>
</tns:getCustomerDetailsRequest>
</soapenv:Body>

</soapenv:Envelope>
3. Donner le code de la classe java ClientCustomerDetails (dans un projet Spring Boot) dans
laquelle vous détaillez la consommation de l’opération getCustomerDetails().
public class ClientCustomer extends WebServiceGatewaySupport {

public GetCustomerDetailsResponse getCustomerDetails(Long id) {

GetCustomerDetailsRequest request = new GetCustomerDetailsRequest;

request.setValue(id);
GetCustomerDetailsResponse response = (GetCustomerDetailsResponse). getWebServiceTemplate()
.marshalSendAndReceive("http://localhost:8080/ws/customers", request,

new SoapActionCallback(
" http://www.tekup.de/ws/CustomerManagementService/GetCustomerDetailsRequest"));
return response;
}
}

2ème Solution : On désire implémenter les opérations qui sont offertes par les web services
OrderManagementService et CustomerManagementService, par un service web Rest en
respectant les contraintes de conception REST (interface uniforme).
4. Donner pour chaque méthode du service REST un exemple d’appel et précisant uniquement
la méthode HTTP utilisée et l’URL complète avec ses paramètres éventuels.
GET http://localhost:8080/api/v1/customers/ GET http://localhost:8080/api/v1/orders/
GET http://localhost:8080/api/v1/customers/{id} POST http://localhost:8080/api/v1/customers/{id}/orders/
POST http://localhost:8080/api/v1/customers/ GET http://localhost:8080/api/v1/orders/{id}
PUT http://localhost:8080/api/v1/customers/{id} GET http://localhost:8080/api/v1/customers/{id}/orders/
DELETE http://localhost:8080/api/v1/customers/{id} PUT http://localhost:8080/api/v1/orders/{id}
DELETE http://localhost:8080/api/v1/orders/{id}

3ème Solution : On veut reprendre cet exemple et proposer un seul endpoint en utilisant
GraphQL (dans un projet Spring Boot). Cet endpoint contient 2 types de données de base :
Customer et Order.
5. Donner un schéma GraphQL pour cet exemple.
enum Status {
received
in_progress
approved
complete
}
type order {
id: ID!
description: String!
amount : Float!
statut: Status!}

type Customer {
id: ID!
firstname: String!
lastname: String!
ordersList: [order!]
}
type Query {
getOrders: [Order]!
getOrderDetails (id: ID):Order
getCustomers :[Customer] !
getCustomersDetails (id: ID): Customer #dans laquelle incluse la reqête getOrdersForCustomers
}
type Mutation {
submitOrder(id: ID, des : String, mt: Float) : Order
updateOrder (id: ID!, s : Status) : Order
cancelOrder (id: ID!) : Boolean
addCustomer (fn : String, ln: String): Customer
updateCustomer (id: ID, fn : String, ln: String ): Customer
deleteCustomer (id: ID): Customer}}
6. Donner le code des classes ClientResolver et ClientMutationResolver.
public class ClientResolver implements GraphQLQueryResolver{

@Autowired
private ClientRepository clientRepository;

public Iterable<Customer> getCustomers () {


return clientRepository.findAll();
}

public Customer getCustomersDetails(Long id) {


Customer c= clientRepository.findById(id).get();
return c;
}
public class ClientResolverMutationResolver implements GraphQLMutationResolver {

@Autowired
private OrderRepository orderRepository;
private CustomerRepository customerRepository;

@Transactional
public Customer addCustomer(Sting fn, String ln){
Customer c=new Customer();
c.setFirstName(fn);
c.setFirstName(ln);
c.setOrderList({});
return Customer.save(c);
}

@Transactional
public Customer updateCustomer(long id, Sting fn, String ln)
{
Customer c= customertRepository.getById(id);
c.setFirstName(fn);
c.setFirstName(ln);
return c;
}
}

@Transactional
public boolean deleteCustomer(Long id) {
customerRepository.deleteById(id);
return true;
}

7. Choisir une solution parmi ces trois, en donnant trois critères pour appuyer votre choix.

Exercice 2
On considère un service Web qui permet aux clients de vendre et d'acheter des produits en ligne.
On s'occupe de la partie de l'application permettant l'ajout, la modification et la consultation de
produits dont les classes (model) sont fournies ci-après.
1. Il vous est demandé d’écrire les classes d’implémentation Java de ce service (model, service
et controller) dans un projet Spring Boot.
On vous fournit les éléments additionnels suivants :
a) le service est disponible à l’URL de base : http://localhost :8080/rest/
b) les produits sont transmis en XML
c) on peut supprimer un produit de 2 manières : en fournissant le produit lui-même ou son
identifiant
d) le id d’un produit modifié, supprimé ou consulté est ajouté comme étape dans le chemin
de l’URL
e) on peut obtenir la liste de tous les produits avec une URL spécifique
f) on peut obtenir la liste des produits correspondant à un des critères de recherche
suivants : le libellé du produit et la ville du propriétaire. Les paramètres sont fournis
comme paramètres de l’URL.
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Personne {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String nom;
private String tel;
private String ville;
@OneToMany(mappedBy = " personne")
private Collection<Produit> produits;

}
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Produit {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String lib;
private double price;
private String cat;
@ManyToOne
private Personne personne;
}

public interface ProduitService {

public List<Produit> ProduitList();


public List<Produit> findByPersonneVille(String ville) ;
public List<Produit> findByLib(String lib) ;
public Produit getOne(Long id);
public Produit save( Produit produit);
public Produit update( Produit produit, Long id);
public void delete(Long id);
public void deleteById (Long id);
}

@Service
public class ProduitServiceImpl implements ProduitService {

@Autowired
private ProduitRepository produitRepository;

public List<Produit> produitList() {


return produitRepository.findAll();
}
public List<Produit> findByLib(String lib) {
return produitRepository.findByPersonneVille (lib);
}
public List<Produit> findByPersonneVille(String ville) {
return produitRepository.findByPersonneVille (ville);
}

public Produit getOne( Long id) {


return produitRepository.findById(id).get();
}
public Produit save( Produit produit) {
return produitRepository.save(produit);
}
public Produit update( Produit produit, Long id) {
produit.setId(id);
return produitRepository.save(produit);
}
public void deleteById (Long id) {
produitRepository.deleteById(id);}
}
public void delete(Produit p) {
produitRepository.delete (p);}}

@RestController
@RequestMapping("/rest")
Public class ProduitRestController {

@Autowired
private ProduitService produitService;

@GetMapping(path = "/produits/",
produces = {MediaType.APPLICATION_XML_VALUE})
public List<Produit> produitList() {
return produitService.produitList();
}
@GetMapping(path = "/produits/byLib/{lib}",
produces = {MediaType.APPLICATION_XML_VALUE})
public List<Produit> findByLib(@PathVariable String lib) {
return produitService.findByLib(lib);
}

@GetMapping(path = "/produits/byTown/{ville}",
produces = {MediaType.APPLICATION_XML_VALUE})
public List<Produit> findByProdVille(@PathVariable String ville) {
return produitService.findByPersonneVille(ville);
}

@GetMapping(path = "/produits/{id}" produces = {MediaType.APPLICATION_XML_VALUE})


public Produit getOne(@PathVariable Long id) {
return produitService.getOne(id);
}
@PostMapping(path = "/produits" produces = {MediaType.APPLICATION_XML_VALUE}
,consumes = {MediaType.APPLICATION_XML_VALUE})
public Produit save(@RequestBody Produit produit) {return produitService.save(produit);
}
@PutMapping(path = "/produits/{id}" produces = {MediaType.APPLICATION_XML_VALUE}
,consumes = {MediaType.APPLICATION_XML_VALUE})
public Produit update(@RequestBody Produit produit, @PathVariable Long id) {
produit.setId(id);
return produitService.save(produit);
}
@DeleteMapping(path = "/produits/{id}")
public void deleteById(@PathVariable Long id) {
produitService.deleteById(id);
}
@DeleteMapping(path = "/produits")
public void delete(@RequestBody Produit p) {
produitService.delete(p);
}
}

2. On désire développer un Rest web service pour effectuer des calculs statistiques sur les
produits créés. Ce service permet d’afficher des statistiques basiques et il va consommer le
service Rest implémenté précédemment. Ecrire les classes d’implémentation Java de ce
service (model, service et controller) dans une projet Spring Boot. La classe Statistique
(model) est fournie ci-après.
 count: contient le nombre total des produits.
 max et min : contiennent respectivement le prix du
produit le plus cher et le moins cher.

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Personne {
private Long id;
private String nom;
private String tel;
private String ville;
private Collection<Produit> produits;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Produit {
private Long id;
private String lib;
private double price;
private String cat;
private Personne personne;}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Statistique {
private Long count;
private double max;
private double min;
}
public interface StatistiqueService {
public Statistique StatistiqueProduit(); }
@Service
public class StatisticServiceImp implements StatisticService {
@Autowired
private RestTemplate restTemplate;
final String URL_PRODUITS = "http://localhost:8080/rest/produits";
get http://localhost:8080/rest/produits: la liste des produit
@Override
public Statistique StatistiqueProduit(){
ResponseEntity<Produit[ ]> response = restTemplate.getForEntity( URL_PRODUITS,
Produit[].class);
Produit[] produits = response.getBody();

var statistics = new Statistique();


statistics.setCount(Arrays.stream(produits).count());
statistics.setMin(Arrays.stream(produits)
.mapToDouble(p -> p.getPrice())
.min().orElse(0));
statistics.setMax(Arrays.stream(produits)
.mapToDouble(p -> p.getPrice())
.max().orElse(0));
return statistics;
}}

You might also like