The sections of this project:
- Swing Application Start
- Bean Validation
- CDI using JBoss Weld SE Container
- RESTful Web Services using HTTP Server
Java source code:
package
kp
Action:
1. With batch file
'01 MVN clean install exec.bat'
build and start the
'Application'.
Screenshot from application main menu.
Action:
1. Push the button "Validation".
Screenshot from "Bean Validation" submenu.
Action:
1. Push the button "Validate Item".
2.1.1. The interface 'ItemCons'
has the property-level constraint with pattern '.*Ret'.
The constraint is placed on the
'ItemCons::getVal' method.
2.1.2. This interface has two implementations:
'ItemConsImplNoCons' and
'ItemConsImplCons'.
Both implementations inherit the constraint from the
'ItemCons' interface.
- The implementation
'ItemConsImplNoCons'
has no constraints in its body.
The implemented method: ' ItemConsImplNoCons::getVal'. - The implementation
'ItemConsImplCons'
has a new additional constraint defined.
This is the field-level constraint with the pattern 'Fld.*' placed on the 'val' field.
The implemented method: ' ItemConsImplCons::getVal'.
2.1.3. In the method
'ResearchValidation::validateItem'
there were validated 4 values with 'jakarta.validation.Validator'.
These values are presented on the tab "Validated Values".
Each value was set in a loop on new instances:
'ItemConsImplNoCons' and
'ItemConsImplCons'.
2.1.4. From the results it is evident what constraints were active in the validation process.
- Class 'ItemConsImplNoCons'
has only one active constraint:
the inherited property-level constraint '.*Ret'. - Class 'ItemConsImplCons'
has two active constraints:
the inherited property-level constraint '.*Ret' and its field-level constraint 'Fld.*'.
Screenshot from "Validate Item" action - tab "Validation Results".
Screenshot from "Validate Item" action - tab "Validated Values".
Action:
1. Push the button "Validate Box Of Items".
2.2.1. The class 'BoxCons' has these constraints:
- a constraint on the field 'list': "Not Null"
- a validation cascading on the field 'list':
validates constraints on the list elements ('ItemConsImplCons' instances) - a constraint on the field 'decimal': between minimal value 10 and maximal value 100
2.2.2. In the method 'ResearchValidation::validateBoxOfItems' there were executed two validations.
2.2.3. In the first validation there were 2 constraint violations:
"not null" for 'list' equals null and "min value 10" for 'decimal' equal 1.
2.2.4. In the second validation there were 4 constraint violations for 'list'.
That list contains 4
'ItemConsImplCons'
objects with values presented on the tab "Validated Values".
The results of that list validation are similar to the results presented in the example "Validate Item" above.
Screenshot from "Validate Box Of Items" action - tab "Validation Results".
Screenshot from "Validate Box Of Items" action - tab "Validated Values".
Action:
1. Push the button "Validate Method".
2.3.1. The interface 'OperCons' has two constraints on method 'OperCons::process':
- a constraint on the method parameter: minimal value 2
- a constraint on the method return value: maximal value 1
2.3.2. In the method 'ResearchValidation::validateOperMethod' there were executed four validations:
- the two validations on the method parameter: the first with value 1 and the second with value 2
- the two validations on the method return value: the first with value 2 and the second with value 1
2.3.3. In the 'method parameters' validation there was a 'parameter constraint' violation:
"min value 2" for parameter equal 1.
2.3.4. In the 'method return value' validation there was a 'return value constraint' violation:
"max value 1" for return value equals 2.
Screenshot from "Validate Method" action.
Action:
1. Push the button "CDI".
The 'ResearchCDIBean'
runs in a Weld SE container. The Weld is the reference implementation of CDI.
Screenshot from "CDI using Weld SE Container" submenu.
Action:
1. Push the button "Alternative & Qualified Beans".
3.1.1. The interface 'BasicBean' has three implementations:
- 'BasicBeanImpl'
- 'BasicBeanImplAlt' - this is the alternative bean
- 'BasicBeanImplScript' - it uses the qualifier '@Script'
3.1.2. The alternative bean
'BasicBeanImplAlt'
is enabled in the bean archive descriptor
'beans.xml'.
The alternative bean is tested with the method
'
ResearchCDIBean::alternativeAndQualifiedBeans'.
3.1.3. The method 'BasicBeanImplScript::show' replaces the alphabetic characters with the Unicode script characters.
3.1.4. Here are used the two instances of the 'BasicBeanImplScript' bean:
- the 1st is injected with the qualifier '@Script'
- the 2nd is selected with the qualifier '@Script' from injected Instance object
3.1.5. Into the 'ResearchCDIBean' there were injected three 'foreseeable' strings with the '@Foreseeable' qualifier:
- 'foreseeable' using default parameters in the qualifier
- 'foreseeable' with different 'ForeseeableDate' (the 'value' parameter was changed from default 'FAR' to 'NEAR')
- 'foreseeable' with customized date format (the 'pattern' parameter replaced)
3.1.6. The method 'ResearchCDIBean::note' presents those three 'foreseeable' objects.
Screenshot from "Alternative & Qualified Beans" action.
3.1.7. The same push button action was repeated with the alternative bean switched off in the file
'beans.xml'.
The result is the replacement of the bean
'BasicBeanImplAlt'
with the bean
'BasicBeanImpl'.
Screenshot from "Alternative & Qualified Beans" action with switched-off alternatives.
Action:
1. Push the button "Decorated Beans".
3.2.1. The interface 'PlainBean' has two implementations:
- 'PlainBeanImpl'
- 'DecoratedBeanImpl' - this is the decorated bean
3.2.2. The decorated bean
'DecoratedBeanImpl'
is enabled in the bean archive descriptor
'beans.xml'.
The decorated bean is tested with the method
'ResearchCDIBean::decoratedBeans'.
3.2.3. The method 'DecoratedBeanImpl::show' calls the method 'PlainBeanImpl::show' two times:
- the 1st time with unchanged content
- the 2nd time with reversed content
Screenshot from "Decorated Beans" action.
3.2.4. The same button action was repeated with the decorated bean switched off in the file
'beans.xml'.
In the results there is only one single call to the
'PlainBeanImpl::show' method.
Screenshot from "Decorated Beans" action with switched-off decorators.
Action:
1. Push the button "Intercepted Beans".
3.3.1. The interceptor class
'ElapsedInterceptor'
is enabled in the bean archive descriptor
'beans.xml'.
The intercepted bean is tested with the method
'ResearchCDIBean::interceptedBeans'.
3.3.2. The interceptor computes in the method
'
ElapsedInterceptor::measure' the method's execution.
The measured bean 'ElapsedBean'
has four methods:
- 'ElapsedBean::notPaused' - runs without any pause (empty method with empty body)
- 'ElapsedBean::pausedNano' - pauses one nanosecond
- 'ElapsedBean::pausedMicro' - pauses one microsecond
- 'ElapsedBean::pausedMilli' - pauses one millisecond
3.3.3. Those four methods were executed in a sequence ten times. The results show that measuring elapsed time with an interceptor was correct only for the 'pausedMilli' method.
Screenshot from "Intercepted Beans" action.
The CDI advantage: no type erasure for the event type.
Action:
1. Push the button "Events".
3.4.1. The events were tested with the method
'ResearchCDIBean::fireEvents'.
There were fired three types of events:
3.4.2. The abstract class
'BasicObserver'
has the method
'BasicObserver::showPayload'.
There are two implementations of the
'BasicObserver' class:
'SmallObserver' and
'BigObserver'.
3.4.3. The 'SmallObserver' class observes only the 'Payload' event in the parent class method 'BasicObserver::showPayload'.
3.4.4. The 'BigObserver' class observes all three events:
- the 'Payload' event in the parent class method ' BasicObserver::showPayload'
- the 'List<Payload>' event in the method ' BigObserver::showPayloadList'
- the 'List<String>' event in the method ' BigObserver::showTextList'
Screenshot from "Events" action.
Examples based on Jersey User Guide.
Screenshot from "RESTful Web Services using HTTP Server" submenu.
Action:
1. Push the button "Content GET".
4.1.1 The method 'ResearchRestful::process'
- creates a new Grizzly HTTP Server instance, which scans for components in kp.restful.data
- starts the JAX-RS client wrapper 'ContentClient'
4.1.2 The
'ContentClient'
gets the content from the root resource
Content' using path and query parameters.
The method
'ContentClient::process'
sends two HTTP requests:
- request with URI ' http://localhost:8080/content/pq/P-a-t-P-a-r?que_par=Q-u-e-P-a-r'
- request with URI ' http://localhost:8080/content/c/P-a-t-P-a-r?que_par=Q-u-e-P-a-r
4.1.3. The 'Content' has two methods with the resource method designator annotation '@GET':
- the method
'Content::getUsingPathAndQuery':
annotations '@PathParam' and '@QueryParam', parameter type 'String' - the method
'Content::getUsingContext':
annotation '@Context', parameter type 'UriInfo'
Screenshot from "Content GET" action.
Action:
1. Push the button "Boxes CRUD (Internal Client)".
4.2.1 The method 'ResearchRestful::process'
- creates a new Grizzly HTTP Server instance, which scans for components in kp.restful.data
- starts the JAX-RS client wrapper 'BoxesClient'
4.2.2 The method 'BoxesClient::process' sends CREATE, READ, UPDATE, and DELETE requests to the 'SetOfBoxes'.
4.2.3 Requests No. 1, No. 2, and No. 3 create three new
'Box' objects.
The resource method
'SetOfBoxes::createBox'
validates
'Box' and puts the created
'Box' in a Map.
It is not idempotent because it uses HTTP POST.
4.2.4 Request No. 4 finds a
'Box'
object with id 1.
The resource method
'SetOfBoxes::readBox'
uses HTTP GET.
4.2.5 Request No. 5 finds all
'Box'
objects and returns the list.
The resource method
'SetOfBoxes::readBoxes'
uses HTTP GET.
4.2.6 The 'Box'
object is updated two times in a row (requests No. 6 and No. 7) with the same data:
id 1 and text "X".
The resource method
'SetOfBoxes::updateBox' validates
'Box' and puts the updated
'Box' in a Map.
It is idempotent because it uses HTTP PUT.
4.2.7 Request No. 8 deletes the
'Box'
object with id 2.
The resource method
'SetOfBoxes::deleteBox'
uses HTTP DELETE.
4.2.8 Request No. 9 reads all
'Box' objects.
Here it is confirmed that the 'Box'
object with id 1 was updated and the
'Box' object with id 2 was deleted.
4.2.9 Requests No. 10 and No. 11 fail after a validation constraint violation.
The validation constraint violation exception returns a response with status code 400 'Bad Request'.
Valid are only texts with the upper case characters (annotation @Pattern in the
'Box' class).
4.2.10 Requests No. 12 and No. 13 fail because 'Box' objects with that id do not exist.
Screenshot from "Boxes CRUD (Internal Client)" action.
Action:
1. Push the button "Boxes CRUD (External Client)".
The main application pauses and the HTTP server starts listening for HTTP requests.
2. Start batch file
'02 CURL call server.bat'.
This script uses 'curl' for sending HTTP requests: POST, GET, PUT, and DELETE.
3. After finishing the execution of the batch file press button 'Enter' in the main window to shut down the server.
The main application resumes running and shows the results in the "Boxes CRUD (External Client)" window.
Screenshot from "Boxes CRUD (External Client)" action.