• Non ci sono risultati.

4.5 Development

4.5.1 Server-side

Using a structured Java Spring as mentioned above, developing a new feature would require us to follow our architecture’s guidelines, meaning we have to create various components, including but not limited to models, services, controllers and the data access objects, with their equivalent in the database if necessary.

Models

In this Spring architecture, a Model is a serializable class used as a communication contract between the controller and the client interacting with it, usually using a different platform.

Models in Spring generally don’t contain any application logic, unlike other approaches where the model acts as both the data contract and data access object, meaning it’s closer to the data layer having direct access to it.

They might of course contain basic methods overriding (equals, contains, etc..).

Below is a code example of a model: Below is an example of a simple model used in this project:

1 p a c k a g e it . p r o j e c t . mo del ;

2 p u b l i c cla ss P r o g e t t o M {

3

4 p r i v a t e int id ;

5 p r i v a t e S t r i n g c o d i c e ;

6 p r i v a t e S t r i n g d e s c r i z i o n e ;

7 p r i v a t e B o o l e a n f l a g V a l ;

8 p r i v a t e B o o l e a n f l a g C l i e n t ;

9 p r i v a t e I n t e g e r i d C l i e n t ;

10 p r i v a t e b o o l e a n f l a g V i s i b l e ;

11 p r i v a t e b o o l e a n f l a g A b i l i t a I n c a r i c o S e m p l i f i c a t o ;

12 p u b l i c int get Id () {

13 r e t u r n id ;

14 }

15 p u b l i c void set Id (int id ) {

16 this. id = id ;

17 }

18 // oth er g e t t e r s and s e t t e r s

19

20 // m e t h o d s o v e r r i d e

21 }

4 – Project

POJOs & FP

POJOs are generally the objects passed to a query to be inserted into the database.

While using FP as mentioned, POJOs extend a base class allowing several operations to be performed. The corresponding table name can also be specified within the class if it’s different than the class name in lower-case.

1 p u b l i c void g e t P r a t i c a (int id ) t h r o w s E x c e p t i o n {

2 try {

3 // F E T C H I N G ONE R E C O R D

4 P r a t i c a p r a t i c a = new P r a t i c a () ;

5 if ( p r a t i c a . s e l e c t (" id ", id ) ) {

6 ..

7 // p r a t i c a now c o n t a i n s the r e c o r d with the id p r o v i d e d

8 }

9 // F E T C H I N G M U L T I P L E R E C O R D

10 BaseList < Pratica > p r a t i c a L i s t = new BaseList <

Pratica >( P r a t i c a .cla ss) ;

11 p r a t i c a L i s t . s e l e c t () ;

12 // p r a t i c a L i s t s h o u l d c o n t a i n a list of P r a t i c a

13 }

14 }

A dependency called Jackson is used by Spring to serialize and to deserialize objects. For generic shallow conversion no additional annotations are required in the Model, while for specific cases, annotations on either field or class level can be added to satisfy our requirements. An example of these annotations would be the

@JsonIgnoreProperties("field1", "field2") annotation that is added on class level and allows, as the name suggest, to ignore specified fields during the serialization and deserialization of the class. Models in this project follow a clear naming convention, which matches the format ClassNameM.

Controllers

A user created component annotated with @Controller having the main purpose of handling requests. It contains a set of methods generally called actions. It also encapsulates the navigation logic and delegates the services for the service object.

Controllers and their actions are identified by at least the name, parameters, path, as well as the request method in order to indicate how this specific action could be reached, these last two can be specified using the annotation @RequestMap-ping(method = RequestMethod.GET, value = "/path/to/users"), providing the request method (typically GET/POST) and path (value) parting from the con-troller’s main path.

Parameters type can vary depending on our diligence using the following two annotations:

• @PathVariable: used to extract any value which is embedded in the URL itself.

• @RequestParam: used to extract query parameters.

The latter being more useful on a traditional web application where data is mostly passed in the query while @PathVariable is more suitable for RESTful web services where the URL contains values (e.g. https://{domain}/valutazione/100023, here data, which is the appraisal’s id is part of the URI.

On each request, Spring makes use of the same Jackson dependency that handles the received data and converts it implicitly into its equivalent POJO. This commu-nication goes in both directions since the same method is used for converting data before returning it, as part of a REST controller for example.

In order to achieve this it is sufficient to add the annotations @ResponseBody and

@RequestBody before our response and parameter data types respectively. The former indicates that a method return value should be bound to the web response body, while the latter indicates that a method parameter should be bound to the body of the web request.

In later versions (as of v4.0) these annotations could also be added on the class level in which case it is inherited and does not need to be added on the method level.

Below is a code snippet from an implemented controller, handling requests related to zones and municipalities (comuni):

4 – Project

1 p a c k a g e it . p r o j e c t . c o n t r o l l e r ;

2

3 @ C o n t r o l l e r

4 @ R e q u e s t M a p p i n g (" / c o m u n i ")

5 p u b l i c cla ss C o m u n e C o n t r o l l e r {

6

7 @ A u t o w i r e d

8 I L o g S e r v i c e l o g S e r v i c e ;

9

10 @ A u t o w i r e d

11 C o m u n i M a p p e r c o m u n i M a p p e r ;

12

13 @ R e q u e s t M a p p i n g ( m e t h o d = R e q u e s t M e t h o d . GET , val ue = " /

")

14 p u b l i c @ R e s p o n s e B o d y List < Comune > g e t L i s t C o m u n i (

@ R e q u e s t P a r a m ( val ue = " q ", r e q u i r e d = fal se) S t r i n g q ) t h r o w s E x c e p t i o n {

15 try {

16 if (! S t r i n g U t i l s . i s E m p t y ( q ) ) {

17 q = q . c o n c a t (" % ") ;

18 }

19 List < Comune > c o m u n i L i s t = c o m u n i M a p p e r . g e t C o m u n i ( q ) ;

20 r e t u r n c o m u n i L i s t ;

21 } c atc h ( E x c e p t i o n e ) {

22 l o g S e r v i c e . log (" E rro r w hi le f e t c h i n g c o m u n e : "

+ e . g e t M e s s a g e () + L o g U t i l s . g e t S t a c k ( e ) , L o g L e v e l s . ER ROR ) ;

23 th row new E x c e p t i o n (" Er ror wh ile l o a d i n g data "

) ;

24 }

25 }

26

27 @ R e q u e s t M a p p i n g ( m e t h o d = R e q u e s t M e t h o d . GET , val ue = "

/{ id } ")

28 p u b l i c @ R e s p o n s e B o d y C o m u n e g e t C o m u n e B y C o d C a t (

@ P a t h V a r i a b l e (" id ") I n t e g e r id ) t h r o w s I t e m N o t F o u n d E x c e p t i o n {

29 try {

30 C o m u n e c o m u n e = c o m u n i M a p p e r . g e t C o m u n e B y I d ( id )

;

31 if ( c o m u n e == null) {

32 c o m u n e = new C o m u n e () ;

33 }

34 r e t u r n c o m u n e ;

35 } c atc h ( E x c e p t i o n e ) {

36 l o g S e r v i c e . log (" O p e r a t i o n f a i l e d " + id + " : "

+ L o g U t i l s . g e t S t a c k ( e ) , L o g L e v e l s . E RRO R ) ;

37 th row new I t e m N o t F o u n d E x c e p t i o n (" U n a b l e to fe tch list " + id ) ;

38 }

39 }

40 }

As seen above custom exceptions come in handy while implementing controllers to help troubleshoot problems.

Services

Services represent the service layer, where the business logic of the application usually resides. Services are annotated by @Service indicated that a class belongs to that layer. This annotation serves as a specialization of @Component, allowing for implementation classes to be auto-detected through classpath scanning. Normally the naming convention followed by service classes is ClassNameI for the interfaces and ClassName for its implementation.

Below we can see the service interface and its implementation. The service contains one method searchConflictOfInterest(int) fetching data using our custom framework.

IConflittiInteresseService.java:

1 p a c k a g e it . e x a m p l e . s e r v i c e ;

2

3 // i m p o r t s

4

5 p u b l i c i n t e r f a c e I V a l u t a z i o n e S e r v i c e {

6

7 p u b l i c List < V a l u t a z i o n e > s e a r c h V a l u t a z i o n e ( E x c e l P r o g e t t o e x c e l P r o g e t t o ) ;

8 9 }

4 – Project

ConflittiInteresseService.java:

1 p a c k a g e it . p r o j e c t . s e r v i c e ;

2

3 // oth er i m p o r t s

4 @ S e r v i c e

5 p u b l i c cla ss V a l u t a z i o n e S e r v i c e i m p l e m e n t s I V a l u t a z i o n e S e r v i c e {

6

7 @ A u t o w i r e d

8 I L o g S e r v i c e l o g S e r v i c e ;

9

10 @ V a l u e (" $ { rank . i n d i r i z z o } ")

11 p r i v a t e int r a n k I n d i r i z z o ;

12

13 @ A u t o w i r e d

14 p r i v a t e V a l u t a z i o n e M a p p e r v a l u t a z i o n e M a p p e r ;

15

16 @ V a l u e (" $ { rank . h e a d e r } ")

17 p r i v a t e int r a n k H e a d e r ;

18

19 p r i v a t e List < V a l u t a z i o n e > s e a r c h V a l u t a z i o n e G e n e r i c ( I n t e g e r id , S t r i n g nome , S t r i n g cognome , S t r i n g codice ,

S t r i n g IVA , S t r i n g indirizzo , B i g D e c i m a l lat ,

B i g D e c i m a l lng , I n t e g e r comune , S t r i n g civico , I n t e g e r i d P r o g e t t o ) {

20

21 // List < V a l u t a z i o n e > l i s t V a l u t a z i o n e = new ArrayList < >() ;

22

23 C a l e n d a r data = C a l e n d a r . g e t I n s t a n c e () ;

24 data . set ( C a l e n d a r . YEAR , data . get ( C a l e n d a r . YEAR ) -1) ;

25 r e t u r n v a l u t a z i o n e M a p p e r . s e a r c h V a l u t a z i o n e ( id , nome , cognome , IVA , indirizzo , comune , civico , data , i d P r o g e t t o ) . p a r a l l e l S t r e a m ()

26 . f i l t e r ( v cEx t -> {

27 if ( vcE xt . g e t I d V a l u t a z i o n e O r i g () !=

vc Ext . g e t I d V a l u t a z i o n e () ) {

28 if (( lat != null) && ( lng != null)

&& ( vcE xt . g e t L a t () != null) && ( vc Ext . g e t L n g () != null ) )

29 r e t u r n true;

30 else

31 r e t u r n c o m u n e . e q u a l s ( vcE xt .

g e t C o m u n e () ) ;

32 }

33 r e t u r n fal se;

34 }) . map ( vcE xt -> vcE xt . t o C o n v e r t I n t o S i m p l e () ) . c o l l e c t ( C o l l e c t o r s . t o L i s t () ) ;

35 }

36

37 @ O v e r r i d e

38 p u b l i c List < V a l u t a z i o n e > s e a r c h V a l u t a z i o n e ( E x c e l P r o g e t t o e x c e l P r o g e t t o ) {

39 S t r i n g nome = null;

40 if ( e x c e l P r o g e t t o . g e t P e r s o n a () != null) {

41 nome = e x c e l P r o g e t t o . g e t N o m e () ;

42 }

43 r e t u r n s e a r c h V a l u t a z i o n e G e n e r i c ( e x c e l P r o g e t t o . g e t E x c e l R o w () , nome , null, null, null, e x c e l P r o g e t t o . g e t I n d i r i z z o () , e x c e l P r o g e t t o . g e t L a t () , e x c e l P r o g e t t o . g e t L n g () , e x c e l P r o g e t t o . g e t C o m u n e () , e x c e l P r o g e t t o . g e t C i v i c o () ) ;

44

45 }

46 }

Dependency Injection One thing we failed to mention describing Spring is dependency injection, a pattern that allows us as programmers to inject objects into a class by using a container that is externally configured (often by an XML file), instead of letting the class directly instantiate the object.[16]

In the service above, the component LogService is injected simply using the annota-tion @Autowired, this way Spring creates a ready-to-use instance of the injected service. Similarly, Spring also allows us to work with values from a properties file with the @Value annotation (see rank above).

4 – Project

Documenti correlati