Associate Professor of Biostatistics and Bioinformatics at Emory University
Ph.D. in Statistics, University of Michigan, 2000
M.S. in Statistics, University of Michigan, 1997
B.S. in Probability and Statistics, Peking University, 1994
Phone:<PHONE_NUMBER>
Fax:<PHONE_NUMBER>
Email<EMAIL_ADDRESS>Address: 1518 Clifton Road Ne, GCR 338, Atlanta, Georgia 30322
Shaojun is a second-year Ph.D. student in the CSI Program at Emory University.
Email<EMAIL_ADDRESS>Address: 201 Dowman Drive, Atlanta, Georgia 30322
Shiyu is a first-year Ph.D. student in the Biostatistics and Bioinformatics Department at Emory University. He is currently working on a project regarding pathway analysis based on genomic data.
Email<EMAIL_ADDRESS>Address: BIOS
Wenjing is a first-year Ph.D. student in the CSI Program at Emory University. She is doing single-cell sequencing data analysis. Her current project leverages single-cell RNA-seq dataset as a reference to detect transcriptomic activity of a certain cell type or sub-cell type in bulk RNA-seq data without deconvolution.
Email<EMAIL_ADDRESS>Address: 201 Dowman Drive, Atlanta, Georgia 30322
Han is....
Kenong is....
Yutong is....
Luxiao is....
Zhiyue Zhao....
Qingyu is ....
Chen Zhao....
Yu Qi....
Yifan Han....
Meng Zhao
Rendong Yang
Li Li
Rich Johnston
Axel Poulet
Jihao Zhou
Hyung Won Choi
Ming Hu
Shyam Gopalakrishnan
Jincheng Shen
Shuai Yuan
Li Chen
Ben Li
Tianlei Xu
Xiaobo Sun
Guodong Yang


A: From the main view in the app, first select the country you are calling to and then tap the name of the contact to initiate the call. If you are low on call time you will be prompted with the option to add time.
A: Express Caller only displays numbers from your address book starting with international dialing prefixes, i.e. +46 for Sweden, +1 for USA etc. Make sure the contacts you want to call are saved in an international format in your phone's address book. Otherwise simply update them and restart the Experess caller app.
A: The app is free to download. You need to buy calling time to your calling destination from inside the app.


 As a professional you define what to expect from a reliable product. To earn the trust of your client you strive for the perfect care solution and an exceptional salon experience.
That’s why we teamed up with stylists from all over the world to create the best Dualsens ever.
Get the best possible support with new Goldwell Dualsenses – developed exclusively for you.
“From really good to
absolutely great”
Shane Bennet
BEAUTIFUL HAIR
IS IN YOUR HANDS
1In all shampoos except Scalp Specialist Shampoos.
2In all color segments: Color, Color Extra Rich, Blondes & Highlights, Silver.
DISCOVER THE BEST
DUALSENSES EVER
» High-performance cutting-edge technologies:
» As gentle as pure water for exceptional reductions in
color wash-out due to innovative FadeStopFormula1
» Instant care infusions and build-in color protection
provided by microPROtec complex
» Tailored performance with selected segment-specific ingredients
» Dedicated Luminescine technology2. The first Goldwell
illuminating color care range from Dualsenses transforming
non-visible UV light into visible light
EXPERIENCE THE SENSUALITY OF BEAUTIFUL HAIR
YOUR PRODUCT CONFIDENCE
» Intuitive usage from self-explanatory assortment
» Memorable product experiences unleashed by modern fragrance
» Salon exclusive innovations connecting Goldwell color and care services
JUST SMOOTH
SILVER
Button
DISCOVER THE OUTCOME OF THREE YEARS OF IDEA SHARING,
WORKING AND CO-CREATING WITH THOUSANDS OF STYLIST WORLDWIDE
COLOR
COLOR EXTRA RICH
CURLY TWIST
RICH REPAIR
BLONDES & HIGHLIGHTS
SCALP SPECIALIST
ULTRA VOLUME
PROFESSIONAL SOLUTIONS FOR INSTANTLY BEAUTIFUL HAIR
Maximize your salon revenue
YOUR TAILORED EDUCATION
YOUR PRODUCT CONFIDENCE
Experience the sensuality of beautiful hair
YOUR SALON POTENTIAL
Become the ultimate care expert
Amplifies a new color luminosity for coloured and
non-colored hair and keeps salon-color vibrant.
For fine to normal hair.
COLOR
Be inspired by these product combinations for the treatments.
» Start consultation easily and customise to all individual care needs
» Profit from a higher care service frequency by offering the new Dualsenses
in-salon treatments
All you need to know about Dualsenses, its usage and the consultation with your client.

ACTIVATION FOLDER
IN-SALON TREATMENTS
Download, install and activate! Discover the new Goldwell Spectrum of Styling app and become a true expert.
A NEW DIMENSION
OF CREATIVITY
Become a true styling expert - with an inspiring catalog of looks and a smart mix of techniques, tools and products.
GOLDWELL SPECTRUM OF STYLING
BENEFIT FROM THE NEW DUALSENSES
AND OUR LIMITED OFFERS
INTRO OFFER:
XXX €
INCLUDES:
ENJOY YOUR
GOLDWELL DUALSENSES
PRODUCTS.
GREAT STYLE STARTS WITH
BEAUTIFUL HAIR
PRODUCTS
SALON POTENTIAL
EDUCATION
INTRO OFFER
JUST SMOOTH
Provides manageability and frizz control with an outstanding soft hair feel and brilliant shine. For unruly and frizzy hair.
Hydrates and defines weightless bounce and elasticity. For naturally wavy, curly and permed hair.
Restores severely damaged hair structures from deep inside and reawakens the shine of natural hair. For dry to damaged hair.
Provides a clean and fresh scalp feeling. Particularly developed products that prevent hereditary hair loss by regular use. For sensitive scalp and thinning hair.
SCALP SPECIALIST
1
2
3
4
5
6
7
BACK TO OVERVIEW
SALON POTENTIAL
CREATIVE TEXTURE
PERFECT HOLD
THE PERFECT MATCH
DUALSENSES & STYLESIGN
Profit from a perfectly complementary care and styling range that is working hand in hand:
Upgrade your services more easily:
» product alliances for outstanding color, care and styling performance
» converging, easy to understand technologies
» effective built-in color protection to enhance beautiful color results
Benefit from an intuitive shelf orientation for your staff and your clients:
» harmonic retail presentation throughout design,
segmentation and fragrance
» transparent self-explanatory product descriptions
» iconic product design with matching color codings and segment names
» supporting well matched at home recommendations
EVERY 3RD
WOMAN IS ANNOYED BY FRIZZY HAIR.2
EVERY 2ND
WOMAN WANTS CURLY HAIR.2
SURPASS YOUR CLIENTS’ EXPECTATIONS
EVERY 2ND
SALON CLIENT GETS A COLOR SERVICE.3
EVERY 2ND
SALON CLIENT IS SUFFERING FROM SCALP PROBLEMS SUCH AS HAIR LOSS.1
1Kline Report 2015, Kline & Company 2000–2016, Germany 22016, Global Hair Care Fact Book, Germany 32016, Hair Dresser Tracking Study, Germany
EVERY 2ND
WOMAN EXPERIENCES DAMAGED HAIR.2
BE THE CARE EXPERT
HALF OF YOURCLIENTS ARE CONCERNED
ABOUT FINE HAIR.2
» Create an attractive in-salon experience with new Dualsenses merchandising
» Set up a harmonic Goodwill retail presentation with the perfect match of new
Dualsenses and StyleSign
» Boost your professional salon sales and generate client demand with
comprehensive sampling opportunities
YOUR SALON POTENTIAL
MAXIMIZE YOUR SALON REVENUE
EXPRESS TREATEMENT
MAKE EVERY MINUTE COUNT
CARE & COLOR TREATMENT
Margharita’s hair needs effective care just as her color needs some refreshment.
DEEP TREATMENT
Create an individual hair care package for every of your clients – by simply combining the Dualsenses care products to an exclusive In-salon treatment menu the way you need it.
Ilva’s hair needs intense help, but she doesn’t want to invest time in complicated applications.
Elana has no time for hair care and needs a really fast treatment.
NOURISHING TREATMENT
Teresa is looking for a very effective hair care without long processing times.
Strengthens each hair fiber from roots to tips and provides lightweight care and enhances fullness. For fine to limp hair.
ULTRA VOLUME
8
9
10
(SHAMPOO)
+
SERUM SPRAY
AND/OR
6 EFFECTS SERUM
BLONDES & HIGHLIGHTS SHAMPOO
+
BLONDES & HIGHLIGHTS
SERUM SPRAY
+
STYLESIGN SMOOTH
CONTROL & SHOWCASER
Additional time without shampooing:
BEAUTIFUL HAIR ACCOMPLISHED IN GREAT STYLE – WITH DUALSENSES AND STYLESIGN
Instant & Easy
DEEP TREATEMENT
CURLY TWIST SHAMPOO
+
CURLY TWIST CONDITIONER
+
CURLY TWIST SERUM
+
STYLESIGN GLAMOUR
WHIP & TWIST AROUND
BEAUTIFUL HAIR ACCOMPLISHED IN GREAT STYLE – WITH DUALSENSES AND STYLESIGN
(SHAMPOO)
+
CONDITIONER
+
SERUM
Intense & Effective
Immediate & Essential
JUST SMOOTH SHAMPOO
+
JUST SMOOTH 60SEC TREATMENT
+
RICH REPAIR 6 EFFECTS SERUM +
STYLESIGN TOP
WHIP & SMOOTH CONTROL
(SHAMPOO)
+
60SEC TREATMENT
+
SERUM SPRAY
AND/OR
6 EFFECTS SERUM
COLOR EXTRA RICH SHAMPOO
+
COLOR EXTRA RICH 60SEC TREATMENT
+
SOFT COLOR
+
STYLESIGN TWIST
AROUND & MAGIC FINISH
(SHAMPOO)
+
60SEC TREATMENT
AND
SOFT COLOR
Care & Color Refresh
BE INSPIRED BY THESE PRODUCT COMBINATIONS
TRAILER
Inspire your clients and introduce them to the new Dualsenses.
GOLDWELL DISPLAY
Benefit from an appealing product presentation
» Easy orientation
» Improved access to products
» Clear price communication
» Visible placement of end-consumer brochure
» Placement of best-seller glorifier
GLORIFIER
Showcase heroes and get your customers’ attention.
BRAND BROCHURE
Be introduced to the new Dualsenses world.
ENDCONSUMER BROCHURE
Get your clients into the new Dualsenses and professionally support them with information on Dualsenses products.
WOBBLER
An eye-catcher to push salon treatments or retail sales.
GREAT SUCCESS IS IN YOUR HANDS
SACHET BOX
Boost your future sales with sampling today. Offer Sachets to potential retail clients and complement trial sizes to buying clients.
IN-SALON TREATEMENT GLORIFIER
Draw your clients’ attention to your in-salon treatment menu and profit from additional turnover.
IN-SALON EXPERIENCE
POSTER/BANNER
Attract new clients with an impressive salon window display.
PILLOW BOX
Perfect for sachets and mini sizes – and keeps them always ready to hand.
1
COLOR EXTRA RICH
Amplifies a new color luminosity for colored and
non-colored hair and keeps salon-color vibrant.
For thick to coarse hair.
BLONDES & HIGHLIGHTS
Brings out color luminosity and neutralizes unwanted yellow tones for blonde color reflections.
For blonde & highlighted hair.
Neutralizes unwanted yellow tones and instantly refines cool effects.
For grey and cool blonde hair.
SILVER


data class TimeWindowInvalid : NotaryError
Occurs when time specified in the TimeWindow command is outside the allowed tolerance.
<init> |
Occurs when time specified in the TimeWindow command is outside the allowed tolerance. TimeWindowInvalid(currentTime: Instant, txTimeWindow: TimeWindow) |
currentTime |
val currentTime: Instant |
txTimeWindow |
val txTimeWindow: TimeWindow |
toString |
fun toString(): String |


About Me
I'm Alberto Alvarez, I'm 23 years old and I was born and raised in a paradise called Venezuela. I came to live in the US 2 years ago, looking for a better future, chasing my goals and dreams which have been always realated to technology and computers, specifically to the coding field.
I believe in a free, open-minded and globalize world. I hate every imaginable and unimaginable way of discrimination and that humans rights are everything and worth fighting for.
Please feel free to send me a message through the contact site, your opinion is very important to me. Thank you


|
SPHinXsys
alpha version
|
Agroup of based particles with essential data. More...
#include <base_particles.h>
Inherited by SPH::ObserverParticles, SPH::RelaxBodyParticles, SPH::SolidBodyParticles, and SPH::WeaklyCompressibleFluidParticles.
Public Member Functions | |
| Particles (string body_name) | |
| Default Constructor. Create a group of particles referred to a body. More... | |
| virtual | ~Particles () |
| Destructor. | |
| virtual void | InitializeAParticle (Vecd pnt, Real particle_volume)=0 |
| Initialize a prticle by input a postion and volume. More... | |
| virtual void | WriteParticlesToVtuFile (ofstream &output_file)=0 |
| Write particle data in VTU format for Paraview. More... | |
| virtual void | WriteParticlesToPltFile (ofstream &output_file)=0 |
| Write particle data in PLT format for Tecplot. More... | |
| virtual void | WriteParticlesToXmlFile (std::string &filefullpath)=0 |
| Write particle data in XML format. More... | |
| virtual void | WriteParticlesToXmlForRestart (std::string &filefullpath)=0 |
| Write particle data in XML format for restart. More... | |
| virtual void | InitialParticleFromRestartXmlFile (std::string &filefullpath)=0 |
| Initialize particle data from restart xml file. | |
| virtual Particles * | PointToThisObject () |
| Pointer to this object. | |
Public Attributes | |
| StdLargeVec< BaseParticleData > | base_particle_data_ |
| size_t | number_of_particles_ |
Protected Attributes | |
| string | body_name_ |
Agroup of based particles with essential data.
| SPH::Particles::Particles | ( | string | body_name | ) |
Default Constructor. Create a group of particles referred to a body.
| [in] | body_name | Name of a body. |
|
pure virtual |
Initialize a prticle by input a postion and volume.
| [in] | pnt | Vecotor of particle position. |
| [in] | particle_volume | Volume of particle. |
Implemented in SPH::MuscleBodyParticles, SPH::ElasticBodyParticles, SPH::Oldroyd_B_FluidParticles, SPH::SolidBodyParticles, SPH::WeaklyCompressibleFluidParticles, SPH::RelaxBodyParticles, and SPH::ObserverParticles.
|
pure virtual |
Write particle data in PLT format for Tecplot.
| [out] | output_file | Ofstream of particle data. |
Implemented in SPH::ElasticBodyParticles, SPH::Oldroyd_B_FluidParticles, SPH::SolidBodyParticles, SPH::WeaklyCompressibleFluidParticles, SPH::RelaxBodyParticles, and SPH::ObserverParticles.
|
pure virtual |
Write particle data in VTU format for Paraview.
| [out] | output_file | Ofstream of particle data. |
Implemented in SPH::ElasticBodyParticles, SPH::Oldroyd_B_FluidParticles, SPH::SolidBodyParticles, SPH::WeaklyCompressibleFluidParticles, SPH::RelaxBodyParticles, and SPH::ObserverParticles.
|
pure virtual |
Write particle data in XML format.
| [out] | filefullpath | Full path to file being write. |
Implemented in SPH::ElasticBodyParticles, SPH::Oldroyd_B_FluidParticles, SPH::SolidBodyParticles, SPH::WeaklyCompressibleFluidParticles, SPH::RelaxBodyParticles, and SPH::ObserverParticles.
|
pure virtual |
Write particle data in XML format for restart.
| [out] | filefullpath | Full path to file being write. |
Implemented in SPH::ElasticBodyParticles, SPH::Oldroyd_B_FluidParticles, SPH::SolidBodyParticles, SPH::WeaklyCompressibleFluidParticles, SPH::RelaxBodyParticles, and SPH::ObserverParticles.
| StdLargeVec<BaseParticleData> SPH::Particles::base_particle_data_ |
Vector of base particle data.
|
protected |
The name of the body in which the particles belongs to.
| size_t SPH::Particles::number_of_particles_ |
Number of particles.


Project Plan¶
Ontomatica will deliver a prototype label application within 60 days of contract start date.
Ontomatica will deliver complete system within 120 days of finalizing a modified specification.
Ontomatica anticipates USDA Label Project will be open-for-business on or about May 26, 2015.
Release 0 is contract signing and start date.
Release 1 is Prototype. Prototype will reuse and modify existing Ontomatica capabilities. For example, deposition services and REST services will not be available for Release 1.
Release 2 is modified specification jointly developed by USDA and Ontomatica.
Release 3 delivers complete system. Release 3 trains USDA level 1 support on use, management and implementation of complete system.


Come and see for yourself.
What do would like to do?
Sun and Sea
Desert Nights
Colonial Sites
Vibrant City
Forrest and Lakes
Vast South
The Great Desert of Atacama.
plan a trip here
The Vibriant City Of Santiago.
plan a trip here
The Magical Forests and Mountains.
plan a trip here
The End of the world is ours.
plan a trip here


Toggle navigation
Azure News Explorer
Search
API
Contact
Explore all Azure News Announcements
Go!
Sort by
Date
Score
Published
Title
Category
More
Add API page here
Add contact page here


Johor to inject RM15 million to boost tourism in 2020
ISKANDAR PUTERI: The Johor government will invest RM15 million (U$S3.5 million) to boost tourism in the state next year, said Chief Minister Dr Sahruddin Jamal on Thursday (Nov 21).
This is the highest allocation of funds for tourism in the state's history, compared to previous amounts which were between RM3 million and RM8 million, said Dr Sahruddin.
READ: Johor rethinks efforts to trump Singapore at tourism
READ: Johor’s lobster haven: Town near Desaru draws visitors with abundant fresh catch
He added that the state economy is expected to bring in as much as RM29.4 billion in 2020 from tourism. Around 18.4 million tourists are also expected, out of which 8.4 million are targeted to be overnight visitors.
The RM15 million allocation will be used mainly on upgrades to infrastructure such as basic amenities at tourist destinations, promotional activities, as well as the hosting of events.
Speaking at the tabling of the Johor 2020 Budget, Dr Sahruddin added that a total of RM8.2 million from the allocation will also be spent on advertising conducted locally and overseas.
READ: More megamalls are being built in Johor Bahru, but how viable are they in the long term?
A portion of the allocation will serve as incentives to travel agents as well, who are able to attract visitors to stay overnight at selected destinations.
Dr Sahruddin added that the state government intended to facilitate the introduction of new travel routes via the Senai International Airport in Johor.


New Password Requested
We have e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly.
{% extends "webshop/base_template.html" %} {% block title %}Nintendo Game & Watch Shop - Password Reset - New Password Requested{% endblock %} {% block extra-scripts %}{% endblock %} {% block page-title %}Password Reset{% endblock %} {% block sort-bar %}{% endblock %} {% block content %}
We have e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly.


Grenfell fire victims lacked common sense, Jacob Rees-Mogg suggests – video
by LBCJacob Rees-Mogg has apologised after claiming Grenfell Tower fire victims did not use 'common sense' and leave the burning building in spite of the London fire brigade's instructions to stay put.
In a statement issued to the Evening Standard, the leader of the House of Commons, said: 'I profoundly apologise. What I meant to say is that I would have also listened to the fire brigade's advice to stay and wait at the time. However, with what we know now and with hindsight I wouldn't and I don't think anyone else would'


[Theta,LogPost,ArVec,PosUpd] = arwm(Pos,NDraw,...)
[Theta,LogPost,ArVec,PosUpd,SgmVec,FinalCov] = arwm(Pos,NDraw,...)
Pos
[ poster ] - Initialised posterior simulator object.
NDraw
[ numeric ] - Length of the chain not including burn-in.
Theta
[ numeric ] - MCMC chain with individual parameters in rows.
LogPost
[ numeric ] - Vector of log posterior density (up to a constant) in each draw.
ArVec
[ numeric ] - Vector of cumulative acceptance ratios.
PosUpd
[ poster ] - Posterior simulator object with its properties updated so to capture the final state of the simulation.
SgmVec
[ numeric ] - Vector of proposal scale factors in each draw.
FinalCov
[ numeric ] - Final proposal covariance matrix; the final covariance matrix of the random walk step is Scale(end)^2*FinalCov.
'adaptProposalCov='
[ numeric | 0.5
] - Speed of adaptation of the Cholesky factor of the proposal covariance matrix towards the target acceptanace ratio, targetAR
; zero means no adaptation.
'adaptScale='
[ numeric | 1
] - Speed of adaptation of the scale factor to deviations of acceptance ratios from the target ratio, targetAR
.
'burnin='
[ numeric | 0.10
] - Number of burn-in draws entered either as a percentage of total draws (between 0 and 1) or directly as a number (integer greater that one). Burn-in draws will be added to the requested number of draws ndraw
and discarded after the posterior simulation.
'estTime='
[ true
| false
] - Display and update the estimated time to go in the command window.
'firstPrefetch='
[ numeric | Inf
] - First draw where parallelised pre-fetching will be used; Inf
means no pre-fetching.
'gamma='
[ numeric | 0.8
] - The rate of decay at which the scale and/or the proposal covariance will be adapted with each new draw.
'initScale='
[ numeric | 1/3
] - Initial scale factor by which the initial proposal covariance will be multiplied; the initial value will be adapted to achieve the target acceptance ratio.
'lastAdapt='
[ numeric | Inf
] - Last point at which the proposal covariance will be adapted; Inf
means adaptation will continue until the last draw. Can also be entered as a percentage of total draws (a number strictly between 0 and 1).
'nStep='
[ numeric | *1
] - Number of pre-fetched steps computed in parallel; only works with firstPrefetch=
smaller than NDraw
.
'progress='
[ true
| false
] - Display progress bar in the command window.
'saveAs='
[ char | empty ] - File name where results will be saved when the option 'saveEvery='
is used.
'saveEvery='
[ numeric | Inf
] - Every N draws will be saved to an HDF5 file, and removed from workspace immediately; no values will be returned in the output arguments Theta
, LogPost
, AR
, Scale
; the option 'saveAs='
must be used to specify the file name; Inf
means a normal run with no saving.
'targetAR='
[ numeric | 0.234
] - Target acceptance ratio.
The function poster/arwm
returns the simulated chain of parameters and the corresponding value of the log posterior density. To obtain simulated sample statistics for each parameter (such as posterior mean, median, percentiles, etc.) use the function poster/stats
to process the simulated chain and calculate the statistics.
The properties of the posterior object returned as the 4th output argument are updated so that they capture the final state of the posterior simulations. This can be used to initialize a next simulation at the point where the previous ended.
Set 'nStep='
greater than 1
, and 'firstPrefetch='
smaller than NDraw
to start a pre-fetching parallelised algorithm (pre-fetched will be all draws starting from 'firstPrefetch='
); to that end, a pool of parallel workers (using e.g. matlabpool
from the Parallel Computing Toolbox) must be opened before calling arwm
.
With pre-fetching, all possible paths 'nStep='
steps ahead (i.e. all possible combinations of reject/accept) are pre-evaluated in parallel, and then the resulting path is selected. Adapation then occurs only every 'nStep='
steps, and hence the results will always somewhat differ from a serial run. Identical results can be obtained by turning down adaptation before pre-fetching starts, i.e. by setting 'lastAdapt='
smaller than 'firstPrefetch='
(and, obviously, by re-setting the random number generator).
Brockwell, A.E., 2005. "Parallel Markov Chain Monte Carlo Simulation by Pre-Fetching," CMU Statistics Dept. Tech. Report 802.
Strid, I., 2009. "Efficient parallelisation of Metropolis-Hastings algorithms using a prefetching approach," SSE/EFI Working Paper Series in Economics and Finance No. 706.


--- layout: page title: About header-img: "img/about-bg.png" ---
I'm here to talk about my passion for coding.


This is a minute ( second) typing test. The timer will begin when you start to type. To the best of your ability, attempt to type as you would normally. This test is designed to correct your typing, and thus is most effective when able to correct the way you actually type.
Beyond the green swelling hills of the Mittel Land rose mighty slopes of forest up to the lofty steeps of the Carpathians themselves. Right and left of us they towered, with the afternoon sun falling full upon them and bringing out all the glorious colours of this beautiful range, deep blue and purple in the shadows of the peaks, green and brown where grass and rock mingled, and an endless perspective of jagged rock and pointed crags, till these were themselves lost in the distance, where the snowy peaks rose grandly. Here and there seemed mighty rifts in the mountains, through which, as the sun began to sink, we saw now and again the white gleam of falling water. One of my companions touched my arm as we swept round the base of a hill and opened up the lofty, snow-covered peak of a mountain, which seemed, as we wound on our serpentine way, to be right before us.


《PPWallet Privacy Policy》
Updated: 2018.09.10
Dear Users,
PPWallet development team (“we”) respects and protects the privacy of Users (“you” or “Users”). Our team will collect and use your Personal Information, generated from your use of PPWallet, in accordance with this Privacy Policy (“Policy”).
1.Information We Collect
1.1 Our wallet is without backstage service,the transfer operation is completed through the BP node.Price information comes from coinmarket open API（https://coinmarketcap.com/zh/api/）,the price will fluctuate,for reference only。
1.2 Your wallet password, private key, mnemonics, and Keystore on the PPWallet do not store or synchronize to the server concerned. We do not provide services to retrieve wallet passwords, private keys, mnemonics, and keystore.
2.How We Use Your Information
2.1 In the process of using PPWallet, we will only save your wallet password, private key, mnemonics, Keystore locally to ensure the normal use of the application. We will not collect and use your information in any way.
3.About The Possibility Of Collecting Your Information Later
3.1 As you know, we will inform you in advance when we collect information from you for future development of the application or for specific purposes, and you have the right to refuse. When you choose to refuse to provide relevant information, it means that you give up the related services using PPWallet.
3.2 Please note that PPWallet will access DApp in the future. You should carefully select and use third party DApp and properly protect your personal information. PPWallet is not responsible for the privacy protection of other third parties.
4.Miscellaneous
4.1 If you are a User outside of PRC, you shall fully understand and conform to the laws, regulations and rules in your jurisdictions which are relevant.
4.2 If you encounter any personal information usage problems while using the service, you can contact us by submitting feedback in PPWallet, etc.
4.3 You can view this policy and other service rules in PPWallet. We encourage you to consult the service agreement and privacy policy every time you use PPWallet.
4.4 Any translated version of this Policy is provided only for the convenience of the user and is not intended to modify the provisions of this Policy. If there is a conflict between the Chinese version of the policy and the non Chinese version, the Chinese version shall prevail.
4.5 This policy shall become effective on September 10, 2018.
by wayne chou


First of all, lets code our ingredients into theme properties. Real themes used in this site will have plenty more properties, but lets show just a bit to keep things simpler:
( "primary-font": Raleway,
"primary-color": hsl(0, 0%, 19%),
"secondary-color": hsl(240, 0%, 63%) )
( "primary-font": Open Sans,
"primary-color": hsl(0, 69%, 67%),
"secondary-color": hsl(174, 62%, 40%) )
( "primary-font": Roboto Mono,
"primary-color": hsl(0, 0%, 5%),
"secondary-color": hsl(57, 90%, 60%) )
Then, we can create a collection of themes very easily. Lets save it in our _theme.scss
file:
$themeCollection: (
"bw": (/* Properties here */),
"peach-azure": (/* Properties here */),
"contrast": (/* Properties here */)
) !default;
Now its time to automatically bind these theme properties to real CSS properties. Here is where magic happens thanks to the SASS mixins. Mixins are just templates that you can reuse on
demand with the add-in of parameters, so we can create a smarter logic inside than just copy/paste chunks of code.
What if we do a generic mixin to themify whatever CSS property with theme values? Lets go for it! This is how the file _mixins.scss
will look like:
@import "themes";
$default-duration: 1.5s;
@mixin themify( $properties,
$keys,
$transition-duration: $default-duration,
$themes: $themeCollection)
{
// Iterate over the themes.
@each $theme, $themeItem in $themes {
// Create a selector CLASS-THEME and also THEME-CLASS.
&.theme-#{$theme},
.theme-#{$theme} & {
// Iterate over each property-key value.
@for $i from 1 through length($properties){
$property: nth($properties,$i);
$key: nth($keys,$i);
#{$property}: map-get($themeItem, $key);
}
// Finally add transitions over themified properties.
transition-property: #{$properties};
transition-duration: $transition-duration;
}
}
}
This code will generate, for every theme, a themified rule to assign the theme value(s) to every input CSS property(s). Note that I have also added transition effect to the themified properties to make theme changing
nicer (unfortunately, a font family change cannot be transitionated).


INTRODUCTION TO TSWALU KALAHARI RESERVE
Tswalu Kalahari Reserve (TKR) is a privately owned nature reserve situated in the Northern Cape province of South Africa (SA) between latitudes -27.5458 to -27.0781 and longitudes 22.1694 to 22.6064.
Established in 1995, it covers an area of + 1 140 km2 and falls within the Eastern Kalahari Bushveld and Kalahari Duneveld Bioregions of SA (Rutherford et al. 2006).
The climate is hot (annual mean temperature = 20 °C) and dry (mean annual rainfall = + 360 mm) with highly variable summer rainfall between December and March (Wataru et al. 2018).
Topography is highly variable, ranging from flat, low lying plains in the east (1019 MASL) to rugged mountains of the Korannaberg in the west (Bloukrans 1590.3 MASL).
As a result, the underlying geology consists of predominantly unconsolidated sediments (87%), followed by metamorphic rocks (13%) and mixed sedimentary rocks (0.3%) (Hartmann and Moosdorf 2012).
Soils are dominated by arenosols [Haplic Arenosols (45%); Luvic Arenosols (16%); Ferralic Arenosols (14%)], which are sandy-textured soils with little humus or clay found typically in deserts (Hengl et al. 2017).
Smaller amounts of cambisols [Chromic Cambisols (17%)] and leptosols [Lithic Leptosols (7%)] with similarly shallow profile depths are also present (Hengl et al. 2017).
These underlying geology and soils give rise to five unique vegetation types described by Mucina and Rutherford (2006) as Gordonia Plains Shrubland (41%); Gordonia Duneveld (23%);
Kathu Bushveld (15%); Koranna - Langeberg Mountain Bushveld (11%); and Olifantshoek Plains Thornveld (11%).
In a recent ecological evaluation of TKR, van Rooyen and van Rooyen (2017) further distinguish 11 different plant communities and describe local environmental variability in more detail
(read full report here).


This page will show the details of a particular park and tables of all the areas (trailheads, parking lots, etc) within the park.
Features
Table of park features here: trail, parking lots, etc.
This page will show the details of a particular park and tables of all the areas (trailheads, parking lots, etc) within the park.
Table of park features here: trail, parking lots, etc.


Each caRuby application component, e.g. caRuby Tissue, presents a JRuby facade for the caBIG application domain API. The caRuby application component is built on caRuby Core, which encapsulates the caCORE data access API. The caTissue API is documented in the caruby-tissue gem. The caCORE API is documented in the caruby-core gem.


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.apache.oro.text.MatchActionProcessor
The MatchActionProcessor class provides AWK-like line by line filtering of a text stream, pattern action pair association, and field splitting based on a registered separator. However, the class can be used with any compatible PatternMatcher/PatternCompiler implementations and need not use the AWK matching classes in org.apache.oro.text.awk. In fact, the default matcher and compiler used by the class are Perl5Matcher and Perl5Compiler from org.apache.oro.text.regex.
To completely understand how to use MatchActionProcessor, you should first
look at MatchAction
and MatchActionInfo
.
A MatchActionProcessor is first initialized with
the desired PatternCompiler and PatternMatcher instances to use to compile
patterns and perform matches. Then, optionally, a field separator may
be registered with setFieldSeparator()
Finally, as many pattern action pairs as desired are registerd with
addAction()
before processing the input
with processMatches()
. Pattern action
pairs are processed in the order they were registered.
The look of added actions can closely mirror that of AWK when anonymous classes are used. Here's an example of how you might use MatchActionProcessor to extract only the second column of a semicolon delimited file:
import java.io.*; import org.apache.oro.text.*; import org.apache.oro.text.regex.*; public final class semicolon { public static final void main(String[] args) { MatchActionProcessor processor = new MatchActionProcessor(); try { processor.setFieldSeparator(";"); // Using a null pattern means to perform the action for every line. processor.addAction(null, new MatchAction() { public void processMatch(MatchActionInfo info) { // We assume the second column exists info.output.println(info.fields.elementAt(1)); } }); } catch(MalformedPatternException e) { e.printStackTrace(); System.exit(1); } try { processor.processMatches(System.in, System.out); } catch(IOException e) { e.printStackTrace(); System.exit(1); } } }You can redirect the following sample input to stdin to test the code:
1;Trenton;New Jersey 2;Annapolis;Maryland 3;Austin;Texas 4;Richmond;Virginia 5;Harrisburg;Pennsylvania 6;Honolulu;Hawaii 7;Santa Fe;New Mexico
MatchAction
,
MatchActionInfo
| Constructor Summary | |
MatchActionProcessor()
Default constructor for MatchActionProcessor. |
|
MatchActionProcessor(PatternCompiler compiler,
PatternMatcher matcher)
Creates a new MatchActionProcessor instance initialized with the specified pattern compiler and matcher. |
| Method Summary | |
void |
addAction(java.lang.String pattern)
Binds a patten to the default action. |
void |
addAction(java.lang.String pattern,
int options)
Binds a patten to the default action, providing options to be used to compile the pattern. |
void |
addAction(java.lang.String pattern,
int options,
MatchAction action)
Registers a pattern action pair, providing options to be used to compile the pattern. |
void |
addAction(java.lang.String pattern,
MatchAction action)
Registers a pattern action pair. |
void |
processMatches(java.io.InputStream input,
java.io.OutputStream output)
This method reads the provided input one line at a time using the platform standart character encoding and for every registered pattern that is contained in the line it executes the associated MatchAction's processMatch() method. |
void |
processMatches(java.io.InputStream input,
java.io.OutputStream output,
java.lang.String encoding)
This method reads the provided input one line at a time and for every registered pattern that is contained in the line it executes the associated MatchAction's processMatch() method. |
void |
processMatches(java.io.Reader input,
java.io.Writer output)
This method reads the provided input one line at a time and for every registered pattern that is contained in the line it executes the associated MatchAction's processMatch() method. |
void |
setFieldSeparator(java.lang.String separator)
Sets the field separator to use when splitting a line into fields. |
void |
setFieldSeparator(java.lang.String separator,
int options)
Sets the field separator to use when splitting a line into fields. |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
public MatchActionProcessor(PatternCompiler compiler, PatternMatcher matcher)
setFieldSeparator()
.
compiler
- The PatternCompiler to use to compile registered
patterns.matcher
- The PatternMatcher to use when searching for matches.public MatchActionProcessor()
MatchActionProcessor(new Perl5Compiler(), new Perl5Matcher());
| Method Detail |
public void addAction(java.lang.String pattern, int options, MatchAction action) throws MalformedPatternException
pattern
- The pattern to bind to an action.options
- The compilation options to use for the pattern.action
- The action to associate with the pattern.
MalformedPatternException
- If the pattern cannot be compiled.public void addAction(java.lang.String pattern, int options) throws MalformedPatternException
pattern
- The pattern to bind to an action.options
- The compilation options to use for the pattern.
MalformedPatternException
- If the pattern cannot be compiled.public void addAction(java.lang.String pattern) throws MalformedPatternException
pattern
- The pattern to bind to an action.
MalformedPatternException
- If the pattern cannot be compiled.public void addAction(java.lang.String pattern, MatchAction action) throws MalformedPatternException
pattern
- The pattern to bind to an action.action
- The action to associate with the pattern.
MalformedPatternException
- If the pattern cannot be compiled.public void setFieldSeparator(java.lang.String separator, int options) throws MalformedPatternException
separator
- A regular expression defining the field separator.options
- The options to use when compiling the separator.
MalformedPatternException
- If the separator cannot be compiled.public void setFieldSeparator(java.lang.String separator) throws MalformedPatternException
separator
- A regular expression defining the field separator.
MalformedPatternException
- If the separator cannot be compiled.public void processMatches(java.io.InputStream input, java.io.OutputStream output, java.lang.String encoding) throws java.io.IOException
setFieldSeparator()
, the
fields member of the MatchActionInfo instance passed to the
processMatch() method is set to a Vector of Strings containing
the split fields of the line. Otherwise the fields member is set
to null. If no match was performed to invoke the action (i.e.,
a null pattern was registered), then the match member is set
to null. Otherwise, the match member will contain the result of
the match.
The input stream, having been exhausted, is closed right before the method terminates and the output stream is flushed.
input
- The input stream from which to read lines.output
- Where to send output.encoding
- The character encoding of the InputStream source.
If you also want to define an output character encoding,
you should use processMatches(Reader, Writer)
and specify the encodings when creating the Reader and
Writer sources and sinks.
java.io.IOException
- If an error occurs while reading input
or writing output.MatchActionInfo
public void processMatches(java.io.InputStream input, java.io.OutputStream output) throws java.io.IOException
setFieldSeparator()
, the
fields member of the MatchActionInfo instance passed to the
processMatch() method is set to a Vector of Strings containing
the split fields of the line. Otherwise the fields member is set
to null. If no match was performed to invoke the action (i.e.,
a null pattern was registered), then the match member is set
to null. Otherwise, the match member will contain the result of
the match.
The input stream, having been exhausted, is closed right before the method terminates and the output stream is flushed.
input
- The input stream from which to read lines.output
- Where to send output.
java.io.IOException
- If an error occurs while reading input
or writing output.MatchActionInfo
public void processMatches(java.io.Reader input, java.io.Writer output) throws java.io.IOException
setFieldSeparator()
, the
fields member of the MatchActionInfo instance passed to the
processMatch() method is set to a Vector of Strings containing
the split fields of the line. Otherwise the fields member is set
to null. If no match was performed to invoke the action (i.e.,
a null pattern was registered), then the match member is set
to null. Otherwise, the match member will contain the result of
the match.
The input stream, having been exhausted, is closed right before the method terminates and the output stream is flushed.
input
- The input stream from which to read lines.output
- Where to send output.
java.io.IOException
- If an error occurs while reading input
or writing output.MatchActionInfo
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


Preface
This tutorial explains how Thymeleaf can be integrated with the Spring Framework, especially (but not only) Spring MVC.
Note that Thymeleaf has integrations for both versions 3.x and 4.x of the Spring Framework, provided by two separate libraries called thymeleaf-spring3
and thymeleaf-spring4
. These libraries are packaged in separate .jar
files (thymeleaf-spring3-{version}.jar
and thymeleaf-spring4-{version}.jar
) and need to be added to your classpath in order to use Thymeleaf’s Spring integrations in your application.
The code samples and example application in this tutorial make use of Spring 4.x and its corresponding Thymeleaf integrations, but the contents of this text are valid also for Spring 3.x. If your application uses Spring 3.x, all you have to do is replace the org.thymeleaf.spring4
package with org.thymeleaf.spring3
in the code samples.
1 Integrating Thymeleaf with Spring
Thymeleaf offers a set of Spring integrations that allow you to use it as a fully-featured substitute for JSP in Spring MVC applications.
These integrations will allow you to:
- Make the mapped methods in your Spring MVC
@Controller
objects forward to templates managed by Thymeleaf, exactly like you do with JSPs. - Use Spring Expression Language (Spring EL) instead of OGNL in your templates.
- Create forms in your templates that are completely integrated with your form-backing beans and result bindings, including the use of property editors, conversion services and validation error handling.
- Display internationalization messages from message files managed by Spring (through the usual
MessageSource
objects). - Resolve your templates using Spring’s own resource resolution mechanisms.
Note that in order to fully understand this tutorial, you should have first gone through the “Using Thymeleaf” tutorial, which explains the Standard Dialect in depth.
2 The SpringStandard Dialect
In order to achieve an easier and better integration, Thymeleaf provides a dialect which specifically implements all the needed features for it to work correctly with Spring.
This specific dialect is based on the Thymeleaf Standard Dialect and is implemented in a class called org.thymeleaf.spring4.dialect.SpringStandardDialect
, which in fact extends from org.thymeleaf.standard.StandardDialect
.
Besides all the features already present in the Standard Dialect –and therefore inherited–, the SpringStandard Dialect introduces the following specific features:
- Use Spring Expression Language (Spring EL or SpEL) as a variable expression language, instead of OGNL. Consequently, all
${...}
and*{...}
expressions will be evaluated by Spring’s Expression Language engine. Note also that support for the Spring EL compiler is available (Spring 4.2.4+). - Access any beans in your application context using SpringEL’s syntax:
${@myBean.doSomething()}
- New attributes for form processing:
th:field
,th:errors
andth:errorclass
, besides a new implementation ofth:object
that allows it to be used for form command selection. - An expression object and method,
#themes.code(...)
, which is equivalent to thespring:theme
JSP custom tag. - An expression object and method,
#mvc.uri(...)
, which is equivalent to thespring:mvcUrl(...)
JSP custom function (only in Spring 4.1+).
Note that most of the times you shouldn’t be using this dialect directly in a normal TemplateEngine
object as a part of its configuration. Unless you have very specific Spring integration needs, you should instead be creating an instance of a new template engine class that performs all the required configuration steps automatically: org.thymeleaf.spring4.SpringTemplateEngine
.
An example bean configuration:
@Bean
public SpringResourceTemplateResolver templateResolver(){
// SpringResourceTemplateResolver automatically integrates with Spring's own
// resource resolution infrastructure, which is highly recommended.
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
// HTML is the default value, added here for the sake of clarity.
templateResolver.setTemplateMode(TemplateMode.HTML);
// Template cache is true by default. Set to false if you want
// templates to be automatically updated when modified.
templateResolver.setCacheable(true);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine automatically applies SpringStandardDialect and
// enables Spring's own MessageSource message resolution mechanisms.
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// Enabling the SpringEL compiler with Spring 4.2.4 or newer can
// speed up execution in most scenarios, but might be incompatible
// with specific cases when expressions in one template are reused
// across different data types, so this flag is "false" by default
// for safer backwards compatibility.
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
Or, using Spring’s XML-based configuration:
<!-- SpringResourceTemplateResolver automatically integrates with Spring's own -->
<!-- resource resolution infrastructure, which is highly recommended. -->
<bean id="templateResolver"
class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<!-- HTML is the default value, added here for the sake of clarity. -->
<property name="templateMode" value="HTML" />
<!-- Template cache is true by default. Set to false if you want -->
<!-- templates to be automatically updated when modified. -->
<property name="cacheable" value="true" />
</bean>
<!-- SpringTemplateEngine automatically applies SpringStandardDialect and -->
<!-- enables Spring's own MessageSource message resolution mechanisms. -->
<bean id="templateEngine"
class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<!-- Enabling the SpringEL compiler with Spring 4.2.4 or newer can speed up -->
<!-- execution in most scenarios, but might be incompatible with specific -->
<!-- cases when expressions in one template are reused across different data -->
<!-- ypes, so this flag is "false" by default for safer backwards -->
<!-- compatibility. -->
<property name="enableSpringELCompiler" value="true" />
</bean>
3 Views and View Resolvers
3.1 Views and View Resolvers in Spring MVC
There are two interfaces in Spring MVC that conform the core of its templating system:
org.springframework.web.servlet.View
org.springframework.web.servlet.ViewResolver
Views model pages in our applications and allow us to modify and predefine their behaviour by defining them as beans. Views are in charge of rendering the actual HTML interface, usually by the execution of some template engine like Thymeleaf.
ViewResolvers are the objects in charge of obtaining View objects for a specific operation and locale. Typically, controllers ask ViewResolvers to forward to a view with a specific name (a String returned by the controller method), and then all the view resolvers in the application execute in ordered chain until one of them is able to resolve that view, in which case a View object is returned and control is passed to it for the renderization of HTML.
Note that not all pages in our applications have to be defined as Views, but only those which behaviour we wish to be non-standard or configured in a specific way (for example, by wiring some special beans to it). If a ViewResolver is asked a view that has no corresponding bean –which is the common case–, a new View object is created ad hoc and returned.
A typical configuration for a JSP+JSTL ViewResolver in a Spring MVC application from the past looked like this:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsps/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
<property name="viewNames" value="*jsp" />
</bean>
A quick look at its properties is enough to know about how it was configured:
viewClass
establishes the class of the View instances. This is needed for a JSP resolver, but it will not be needed at all when we’re working with Thymeleaf.prefix
andsuffix
work in a similar way to the attributes of the same names in Thymeleaf’s TemplateResolver objects.order
establishes the order in which the ViewResolver will be queried in the chain.viewNames
allows the definition (with wildcards) of the view names that will be resolved by this ViewResolver.
3.2 Views and View Resolvers in Thymeleaf
Thymeleaf offers implementations for the two interfaces mentioned above:
org.thymeleaf.spring4.view.ThymeleafView
org.thymeleaf.spring4.view.ThymeleafViewResolver
These two classes will be in charge of processing Thymeleaf templates as a result of the execution of controllers.
Configuration of the Thymeleaf View Resolver is very similar to that of JSP:
@Bean
public ThymeleafViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
// NOTE 'order' and 'viewNames' are optional
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
return viewResolver;
}
…or in XML:
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<!-- NOTE 'order' and 'viewNames' are optional -->
<property name="order" value="1" />
<property name="viewNames" value="*.html,*.xhtml" />
</bean>
The templateEngine
parameter is, of course, the SpringTemplateEngine
object we defined in the previous chapter. The other two (order
and viewNames
) are both optional, and have the same meaning as in the JSP ViewResolver we saw before.
Note that we do not need prefix
or suffix
parameters, because these are already specified at the Template Resolver (which in turn is passed to the Template Engine).
And what if we wanted to define a View
bean and add some static variables to it? Easy, just define a prototype bean for it:
@Bean
@Scope("prototype")
public ThymeleafView mainView() {
ThymeleafView view = new ThymeleafView("main"); // templateName = 'main'
view.setStaticVariables(
Collections.singletonMap("footer", "The ACME Fruit Company"));
return view;
}
By doing this, you will be able to execute specifically this view bean selecting it by bean name (mainView
, in this case).
4 Spring Thyme Seed Starter Manager
The source code for the examples shown in this and future chapters of this guide can be found in the Spring Thyme Seed Starter Manager GitHub repository.
4.1 The Concept
At Thymeleaf we’re huge fans of thyme, and every spring we prepare our seed starting kits with good soil and our favourite seeds, place them under the Spanish sun and patiently wait for our new plants to grow.
But this year we got fed up with sticking labels to the seed starter containers for knowing which seed was in each cell of the container, so we decided to prepare an application using Spring MVC and Thymeleaf to help us catalogue our starters: The Spring Thyme SeedStarter Manager.
In a similar way to the Good Thymes Virtual Grocery application we developed in the Using Thymeleaf tutorial, the STSM will allow us to exemplify the most important aspects of the integration of Thymeleaf as a template engine for Spring MVC.
4.2 Business Layer
We will need a very simple business layer for our application. First of all, let’s have a look at our model entities:
A couple of very simple service classes will provide the required business methods. Like:
@Service
public class SeedStarterService {
@Autowired
private SeedStarterRepository seedstarterRepository;
public List<SeedStarter> findAll() {
return this.seedstarterRepository.findAll();
}
public void add(final SeedStarter seedStarter) {
this.seedstarterRepository.add(seedStarter);
}
}
And:
@Service
public class VarietyService {
@Autowired
private VarietyRepository varietyRepository;
public List<Variety> findAll() {
return this.varietyRepository.findAll();
}
public Variety findById(final Integer id) {
return this.varietyRepository.findById(id);
}
}
4.3 Spring MVC configuration
Next we need to set up the Spring MVC configuration for the application, which will include not only the standard Spring MVC artifacts like resource handling or annotation scanning, but also the creation of the Template Engine and View Resolver instances.
@Configuration
@EnableWebMvc
@ComponentScan
public class SpringWebConfig
extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private ApplicationContext applicationContext;
public SpringWebConfig() {
super();
}
public void setApplicationContext(final ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
/* ******************************************************************* */
/* GENERAL CONFIGURATION ARTIFACTS */
/* Static Resources, i18n Messages, Formatters (Conversion Service) */
/* ******************************************************************* */
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("Messages");
return messageSource;
}
@Override
public void addFormatters(final FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatter(varietyFormatter());
registry.addFormatter(dateFormatter());
}
@Bean
public VarietyFormatter varietyFormatter() {
return new VarietyFormatter();
}
@Bean
public DateFormatter dateFormatter() {
return new DateFormatter();
}
/* **************************************************************** */
/* THYMELEAF-SPECIFIC ARTIFACTS */
/* TemplateResolver <- TemplateEngine <- ViewResolver */
/* **************************************************************** */
@Bean
public SpringResourceTemplateResolver templateResolver(){
// SpringResourceTemplateResolver automatically integrates with Spring's own
// resource resolution infrastructure, which is highly recommended.
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
// HTML is the default value, added here for the sake of clarity.
templateResolver.setTemplateMode(TemplateMode.HTML);
// Template cache is true by default. Set to false if you want
// templates to be automatically updated when modified.
templateResolver.setCacheable(true);
return templateResolver;
}
@Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine automatically applies SpringStandardDialect and
// enables Spring's own MessageSource message resolution mechanisms.
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// Enabling the SpringEL compiler with Spring 4.2.4 or newer can
// speed up execution in most scenarios, but might be incompatible
// with specific cases when expressions in one template are reused
// across different data types, so this flag is "false" by default
// for safer backwards compatibility.
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
@Bean
public ThymeleafViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
}
4.4 The Controller
Of course, we will also need a controller for our application. As the STSM will only contain one web page with a list of seed starters and a form for adding new ones, we will write only one controller class for all the server interactions:
@Controller
public class SeedStarterMngController {
@Autowired
private VarietyService varietyService;
@Autowired
private SeedStarterService seedStarterService;
...
}
Now let’s see what we can add to this controller class.
Model Attributes
First we will add some model attributes that we will need in the page:
@ModelAttribute("allTypes")
public List<Type> populateTypes() {
return Arrays.asList(Type.ALL);
}
@ModelAttribute("allFeatures")
public List<Feature> populateFeatures() {
return Arrays.asList(Feature.ALL);
}
@ModelAttribute("allVarieties")
public List<Variety> populateVarieties() {
return this.varietyService.findAll();
}
@ModelAttribute("allSeedStarters")
public List<SeedStarter> populateSeedStarters() {
return this.seedStarterService.findAll();
}
Mapped methods
And now the most important part of a controller, the mapped methods: one for showing the form page, and another one for processing the addition of new SeedStarter
objects.
@RequestMapping({"/","/seedstartermng"})
public String showSeedstarters(final SeedStarter seedStarter) {
seedStarter.setDatePlanted(Calendar.getInstance().getTime());
return "seedstartermng";
}
@RequestMapping(value="/seedstartermng", params={"save"})
public String saveSeedstarter(
final SeedStarter seedStarter, final BindingResult bindingResult, final ModelMap model) {
if (bindingResult.hasErrors()) {
return "seedstartermng";
}
this.seedStarterService.add(seedStarter);
model.clear();
return "redirect:/seedstartermng";
}
4.5 Configuring a Conversion Service
In order to allow easy formatting of Date
and also Variety
objects in our view layer, we configured our application so that a Spring ConversionService
object was created and initialized (by the WebMvcConfigurerAdapter
we extend) with a couple of formatter objects we will need. See it again:
@Override
public void addFormatters(final FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatter(varietyFormatter());
registry.addFormatter(dateFormatter());
}
@Bean
public VarietyFormatter varietyFormatter() {
return new VarietyFormatter();
}
@Bean
public DateFormatter dateFormatter() {
return new DateFormatter();
}
Spring formatters are implementations of the org.springframework.format.Formatter
interface. For more information on how the Spring conversion infrastructure works, see the docs at spring.io.
Let’s have a look at the DateFormatter
, which formats dates according to a format string present at the date.format
message key of our Messages.properties
:
public class DateFormatter implements Formatter<Date> {
@Autowired
private MessageSource messageSource;
public DateFormatter() {
super();
}
public Date parse(final String text, final Locale locale) throws ParseException {
final SimpleDateFormat dateFormat = createDateFormat(locale);
return dateFormat.parse(text);
}
public String print(final Date object, final Locale locale) {
final SimpleDateFormat dateFormat = createDateFormat(locale);
return dateFormat.format(object);
}
private SimpleDateFormat createDateFormat(final Locale locale) {
final String format = this.messageSource.getMessage("date.format", null, locale);
final SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setLenient(false);
return dateFormat;
}
}
The VarietyFormatter
automatically converts between our Variety
entities and the way we want to use them in our forms (basically, by their id
field values):
public class VarietyFormatter implements Formatter<Variety> {
@Autowired
private VarietyService varietyService;
public VarietyFormatter() {
super();
}
public Variety parse(final String text, final Locale locale) throws ParseException {
final Integer varietyId = Integer.valueOf(text);
return this.varietyService.findById(varietyId);
}
public String print(final Variety object, final Locale locale) {
return (object != null ? object.getId().toString() : "");
}
}
We will learn more on how these formatters affect the way our data is displayed later on.
5 Listing Seed Starter Data
The first thing that our /WEB-INF/templates/seedstartermng.html
page will show is a listing with the seed starters currently stored. For this we will need some externalized messages and also some expression evaluation on model attributes. Like this:
<div class="seedstarterlist" th:unless="${#lists.isEmpty(allSeedStarters)}">
<h2 th:text="#{title.list}">List of Seed Starters</h2>
<table>
<thead>
<tr>
<th th:text="#{seedstarter.datePlanted}">Date Planted</th>
<th th:text="#{seedstarter.covered}">Covered</th>
<th th:text="#{seedstarter.type}">Type</th>
<th th:text="#{seedstarter.features}">Features</th>
<th th:text="#{seedstarter.rows}">Rows</th>
</tr>
</thead>
<tbody>
<tr th:each="sb : ${allSeedStarters}">
<td th:text="${{sb.datePlanted}}">13/01/2011</td>
<td th:text="#{|bool.${sb.covered}|}">yes</td>
<td th:text="#{|seedstarter.type.${sb.type}|}">Wireframe</td>
<td th:text="${#strings.arrayJoin(
#messages.arrayMsg(
#strings.arrayPrepend(sb.features,'seedstarter.feature.')),
', ')}">Electric Heating, Turf</td>
<td>
<table>
<tbody>
<tr th:each="row,rowStat : ${sb.rows}">
<td th:text="${rowStat.count}">1</td>
<td th:text="${row.variety.name}">Thymus Thymi</td>
<td th:text="${row.seedsPerCell}">12</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
Lots to see here. Let’s have a look at each fragment separately.
First of all, this section will only be shown if there are any seed starters. We achieve that with a th:unless attribute and the #lists.isEmpty(...)
function.
<div class="seedstarterlist" th:unless="${#lists.isEmpty(allSeedStarters)}">
Note that all utility objects like #lists
are available in Spring EL expressions just as they were in OGNL expressions in the Standard Dialect.
The next thing to see is a lot of internationalized (externalized) texts, like:
<h2 th:text="#{title.list}">List of Seed Starters</h2>
<table>
<thead>
<tr>
<th th:text="#{seedstarter.datePlanted}">Date Planted</th>
<th th:text="#{seedstarter.covered}">Covered</th>
<th th:text="#{seedstarter.type}">Type</th>
<th th:text="#{seedstarter.features}">Features</th>
<th th:text="#{seedstarter.rows}">Rows</th>
...
This being a Spring MVC application, we already defined a MessageSource
bean in our Spring configuration (MessageSource
objects are the standard way of managing externalized texts in Spring MVC):
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("Messages");
return messageSource;
}
…and that basename
property indicates that we will have files like Messages_es.properties
or Messages_en.properties
in our classpath. Let’s have a look at the Spanish version:
title.list=Lista de semilleros
date.format=dd/MM/yyyy
bool.true=sí
bool.false=no
seedstarter.datePlanted=Fecha de plantación
seedstarter.covered=Cubierto
seedstarter.type=Tipo
seedstarter.features=Características
seedstarter.rows=Filas
seedstarter.type.WOOD=Madera
seedstarter.type.PLASTIC=Plástico
seedstarter.feature.SEEDSTARTER_SPECIFIC_SUBSTRATE=Sustrato específico para semilleros
seedstarter.feature.FERTILIZER=Fertilizante
seedstarter.feature.PH_CORRECTOR=Corrector de PH
In the first column of the table listing we will show the date when the seed starter was prepared. But we will show it formatted in the way we defined in our DateFormatter
. In order to do that we will use the double-brace syntax (${{...}}
), which will automatically apply the Spring Conversion Service, including the DateFormatter
we registered at configuration.
<td th:text="${{sb.datePlanted}}">13/01/2011</td>
Next is showing whether the seed starter container is covered or not, by transforming the value of the boolean covered bean property into an internationalized “yes” or “no” with a literal substitution expression:
<td th:text="#{|bool.${sb.covered}|}">yes</td>
Now we have to show the type of seed starter container. Type is a java enum with two values (WOOD
and PLASTIC
), and that’s why we defined two properties in our Messages
file called seedstarter.type.WOOD
and seedstarter.type.PLASTIC
.
But in order to obtain the internationalized names of the types, we will need to add the seedstarter.type.
prefix to the enum value by means of an expression, which result we will then use as the message key:
<td th:text="#{|seedstarter.type.${sb.type}|}">Wireframe</td>
The most difficult part of this listing is the features column. In it we want to display all the features of our container —that come in the form of an array of Feature
enums—, separated by commas. Like “Electric Heating, Turf”.
Note that this is particularly difficult because these enum values also need to be externalized, as we did with Types. The flow is then:
- Prepend the corresponding prefix to all the elements of the
features
array. - Obtain the externalized messages corresponding to all the keys from step 1.
- Join all the messages obtained in step 2, using a comma as a delimiter.
For achieving this, we create the following code:
<td th:text="${#strings.arrayJoin(
#messages.arrayMsg(
#strings.arrayPrepend(sb.features,'seedstarter.feature.')),
', ')}">Electric Heating, Turf</td>
The last column of our listing will be quite simple, in fact. Even if it has a nested table for showing the contents of each row in the container:
<td>
<table>
<tbody>
<tr th:each="row,rowStat : ${sb.rows}">
<td th:text="${rowStat.count}">1</td>
<td th:text="${row.variety.name}">Thymus Thymi</td>
<td th:text="${row.seedsPerCell}">12</td>
</tr>
</tbody>
</table>
</td>
6 Creating a Form
6.1 Handling the command object
Command object is the name Spring MVC gives to form-backing beans, this is, to objects that model a form’s fields and provide getter and setter methods that will be used by the framework for establishing and obtaining the values input by the user at the browser side.
Thymeleaf requires you to specify the command object by using a th:object
attribute in your <form>
tag:
<form action="#" th:action="@{/seedstartermng}" th:object="${seedStarter}" method="post">
...
</form>
This is consistent with other uses of th:object,
but in fact this specific scenario adds some limitations in order to correctly integrate with Spring MVC’s infrastructure:
- Values for
th:object
attributes in form tags must be variable expressions (${...}
) specifying only the name of a model attribute, without property navigation. This means that an expression like${seedStarter}
is valid, but${seedStarter.data}
would not be. - Once inside the
<form>
tag, no otherth:object
attribute can be specified. This is consistent with the fact that HTML forms cannot be nested.
6.2 Inputs
Let’s see now how to add an input to our form:
<input type="text" th:field="*{datePlanted}" />
As you can see, we are introducing a new attribute here: th:field.
This is a very important feature for Spring MVC integration because it does all the heavy work of binding your input with a property in the form-backing bean. You can see it as an equivalent of the path attribute in a
The th:field
attribute behaves differently depending on whether it is attached to an <input>
, <select>
or <textarea>
tag (and also depending on the specific type of <input>
tag). In this case (input[type=text]
), the above line of code is similar to:
<input type="text" id="datePlanted" name="datePlanted" th:value="*{datePlanted}" />
…but in fact it is a little bit more than that, because th:field
will also apply the registered Spring Conversion Service, including the DateFormatter
we saw before (even if the field expression is not double-bracketed). Thanks to this, the date will be shown correctly formatted.
Values for th:field
attributes must be selection expressions (*{...}
), which makes sense given the fact that they will be evaluated on the form-backing bean and not on the context variables (or model attributes in Spring MVC jargon).
Contrary to the ones in th:object
, these expressions can include property navigation (in fact any expression allowed for the path attribute of a <form:input>
JSP tag will be allowed here).
Note that th:field
also understands the new types of <input>
element introduced by HTML5 like <input type="datetime" ... />
, <input type="color" ... />
, etc., effectively adding complete HTML5 support to Spring MVC.
6.3 Checkbox fields
th:field
also allows us to define checkbox inputs. Let’s see an example from our HTML page:
<div>
<label th:for="${#ids.next('covered')}" th:text="#{seedstarter.covered}">Covered</label>
<input type="checkbox" th:field="*{covered}" />
</div>
Note there’s some fine stuff here besides the checkbox itself, like an externalized label and also the use of the #ids.next('covered')
function for obtaining the value that will be applied to the id attribute of the checkbox input.
Why do we need this dynamic generation of an id attribute for this field? Because checkboxes are potentially multi-valued, and thus their id values will always be suffixed a sequence number (by internally using the #ids.seq(...)
function) in order to ensure that each of the checkbox inputs for the same property has a different id value.
We can see this more easily if we look at such a multi-valued checkbox field:
<ul>
<li th:each="feat : ${allFeatures}">
<input type="checkbox" th:field="*{features}" th:value="${feat}" />
<label th:for="${#ids.prev('features')}"
th:text="#{${'seedstarter.feature.' + feat}}">Heating</label>
</li>
</ul>
Note that we’ve added a th:value
attribute this time, because the features field is not a boolean like covered was, but instead is an array of values.
Let’s see the HTML output generated by this code:
<ul>
<li>
<input id="features1" name="features" type="checkbox" value="SEEDSTARTER_SPECIFIC_SUBSTRATE" />
<input name="_features" type="hidden" value="on" />
<label for="features1">Seed starter-specific substrate</label>
</li>
<li>
<input id="features2" name="features" type="checkbox" value="FERTILIZER" />
<input name="_features" type="hidden" value="on" />
<label for="features2">Fertilizer used</label>
</li>
<li>
<input id="features3" name="features" type="checkbox" value="PH_CORRECTOR" />
<input name="_features" type="hidden" value="on" />
<label for="features3">PH Corrector used</label>
</li>
</ul>
We can see here how a sequence suffix is added to each input’s id attribute, and how the #ids.prev(...)
function allows us to retrieve the last sequence value generated for a specific input id.
Don’t worry about those hidden inputs with
name="_features"
: they are automatically added in order to avoid problems with browsers not sending unchecked checkbox values to the server upon form submission.
Also note that if our features property contained some selected values in our form-backing bean, th:field
would have taken care of that and would have added a checked="checked"
attribute to the corresponding input tags.
6.5 Dropdown/List selectors
Select fields have two parts: the <select>
tag and its nested <option>
tags. When creating this kind of field, only the <select>
tag has to include a th:field
attribute, but the th:value
attributes in the nested <option>
tags will be very important because they will provide the means of knowing which is the currently selected option (in a similar way to non-boolean checkboxes and radio buttons).
Let’s re-build the type field as a dropdown select:
<select th:field="*{type}">
<option th:each="type : ${allTypes}"
th:value="${type}"
th:text="#{${'seedstarter.type.' + type}}">Wireframe</option>
</select>
At this point, understanding this piece of code is quite easy. Just notice how attribute precedence allows us to set the th:each
attribute in the <option>
tag itself.
6.6 Dynamic fields
Thanks to the advanced form-field binding capabilities in Spring MVC, we can use complex Spring EL expressions to bind dynamic form fields to our form-backing bean. This will allow us to create new Row objects in our SeedStarter
bean, and to add those rows’ fields to our form at user request.
In order to do this, we will need a couple of new mapped methods in our controller, which will add or remove a row from our SeedStarter
depending on the existence of specific request parameters:
@RequestMapping(value="/seedstartermng", params={"addRow"})
public String addRow(final SeedStarter seedStarter, final BindingResult bindingResult) {
seedStarter.getRows().add(new Row());
return "seedstartermng";
}
@RequestMapping(value="/seedstartermng", params={"removeRow"})
public String removeRow(
final SeedStarter seedStarter, final BindingResult bindingResult,
final HttpServletRequest req) {
final Integer rowId = Integer.valueOf(req.getParameter("removeRow"));
seedStarter.getRows().remove(rowId.intValue());
return "seedstartermng";
}
And now we can add a dynamic table to our form:
<table>
<thead>
<tr>
<th th:text="#{seedstarter.rows.head.rownum}">Row</th>
<th th:text="#{seedstarter.rows.head.variety}">Variety</th>
<th th:text="#{seedstarter.rows.head.seedsPerCell}">Seeds per cell</th>
<th>
<button type="submit" name="addRow" th:text="#{seedstarter.row.add}">Add row</button>
</th>
</tr>
</thead>
<tbody>
<tr th:each="row,rowStat : *{rows}">
<td th:text="${rowStat.count}">1</td>
<td>
<select th:field="*{rows[__${rowStat.index}__].variety}">
<option th:each="var : ${allVarieties}"
th:value="${var.id}"
th:text="${var.name}">Thymus Thymi</option>
</select>
</td>
<td>
<input type="text" th:field="*{rows[__${rowStat.index}__].seedsPerCell}" />
</td>
<td>
<button type="submit" name="removeRow"
th:value="${rowStat.index}" th:text="#{seedstarter.row.remove}">Remove row</button>
</td>
</tr>
</tbody>
</table>
Quite a lot of things to see here, but not much we should not understand by now… except for one strange
thing:
<select th:field="*{rows[__${rowStat.index}__].variety}">
...
</select>
If you recall from the “Using Thymeleaf” tutorial, that __${...}__
syntax is a preprocessing expression, which is an inner expression that is evaluated before actually evaluating the whole expression. But why that way of specifying the row index? Wouldn’t it be enough with:
<select th:field="*{rows[rowStat.index].variety}">
...
</select>
…well, actually, no. The problem is that Spring EL does not evaluate variables inside array index brackets, so when executing the above expression we would obtain an error telling us that rows[rowStat.index]
(instead of rows[0]
, rows[1]
, etc) is not a valid position in the rows collection. That’s why preprocessing is needed here.
Let’s have a look at a fragment of the resulting HTML after pressing “Add Row” a couple of times:
<tbody>
<tr>
<td>1</td>
<td>
<select id="rows0.variety" name="rows[0].variety">
<option selected="selected" value="1">Thymus vulgaris</option>
<option value="2">Thymus x citriodorus</option>
<option value="3">Thymus herba-barona</option>
<option value="4">Thymus pseudolaginosus</option>
<option value="5">Thymus serpyllum</option>
</select>
</td>
<td>
<input id="rows0.seedsPerCell" name="rows[0].seedsPerCell" type="text" value="" />
</td>
<td>
<button name="removeRow" type="submit" value="0">Remove row</button>
</td>
</tr>
<tr>
<td>2</td>
<td>
<select id="rows1.variety" name="rows[1].variety">
<option selected="selected" value="1">Thymus vulgaris</option>
<option value="2">Thymus x citriodorus</option>
<option value="3">Thymus herba-barona</option>
<option value="4">Thymus pseudolaginosus</option>
<option value="5">Thymus serpyllum</option>
</select>
</td>
<td>
<input id="rows1.seedsPerCell" name="rows[1].seedsPerCell" type="text" value="" />
</td>
<td>
<button name="removeRow" type="submit" value="1">Remove row</button>
</td>
</tr>
</tbody>
7 Validation and Error Messages
Most of our forms will need to show validation messages in order to inform the user of the errors he/she has made.
Thymeleaf offers some tools for this: a couple of functions in the #fields
object, the th:errors
and the th:errorclass
attributes.
7.1 Field errors
Let’s see how we could set a specific CSS class to a field if it has an error:
<input type="text" th:field="*{datePlanted}"
th:class="${#fields.hasErrors('datePlanted')}? fieldError" />
As you can see, the #fields.hasErrors(...)
function receives the field expression as a parameter (datePlanted
), and returns a boolean telling whether any validation errors exist for that field.
We could also obtain all the errors for that field and iterate them:
<ul>
<li th:each="err : ${#fields.errors('datePlanted')}" th:text="${err}" />
</ul>
Instead of iterating, we could have also used th:errors
, a specialized attribute which builds a list with all the errors for the specified selector, separated by <br />
:
<input type="text" th:field="*{datePlanted}" />
<p th:if="${#fields.hasErrors('datePlanted')}" th:errors="*{datePlanted}">Incorrect date</p>
Simplifying error-based CSS styling: th:errorclass
The example we saw above, setting a CSS class to a form input if that field has errors, is so common that Thymeleaf offers a specific attribute for doing exacly that: th:errorclass
.
Applied to a form field tag (input, select, textarea…), it will read the name of the field to be examined from any existing name
or th:field
attributes in the same tag, and then append the specified CSS class to the tag if such field has any associated errors:
<input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" />
If datePlanted
has errors, this will render as:
<input type="text" id="datePlanted" name="datePlanted" value="2013-01-01" class="small fieldError" />
7.2 All errors
And what if we want to show all the errors in the form? We just need to query the #fields.hasErrors(...)
and #fields.errors(...)
methods with the '*'
or 'all'
constants (which are equivalent):
<ul th:if="${#fields.hasErrors('*')}">
<li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect</li>
</ul>
As in the examples above, we could obtain all the errors and iterate them…
<ul>
<li th:each="err : ${#fields.errors('*')}" th:text="${err}" />
</ul>
…as well as build a <br />
-separated list:
<p th:if="${#fields.hasErrors('all')}" th:errors="*{all}">Incorrect date</p>
Finally note that #fields.hasErrors('*')
is equivalent to #fields.hasAnyErrors()
and #fields.errors('*')
is equivalent to #fields.allErrors()
. Use whichever syntax you prefer:
<div th:if="${#fields.hasAnyErrors()}">
<p th:each="err : ${#fields.allErrors()}" th:text="${err}">...</p>
</div>
7.3 Global errors
There is a third type of error in a Spring form: global errors. These are errors that are not associated with any specific fields in the form, but still exist.
Thymeleaf offers the global
constant for accessing these errors:
<ul th:if="${#fields.hasErrors('global')}">
<li th:each="err : ${#fields.errors('global')}" th:text="${err}">Input is incorrect</li>
</ul>
<p th:if="${#fields.hasErrors('global')}" th:errors="*{global}">Incorrect date</p>
…as well as equivalent #fields.hasGlobalErrors()
and #fields.globalErrors()
convenience methods:
<div th:if="${#fields.hasGlobalErrors()}">
<p th:each="err : ${#fields.globalErrors()}" th:text="${err}">...</p>
</div>
7.4 Displaying errors outside forms
Form validation errors can also be displayed outside forms by using variable (${...}
) instead of selection (*{...}
) expressions and prefixing the name of the form-backing bean:
<div th:errors="${myForm}">...</div>
<div th:errors="${myForm.date}">...</div>
<div th:errors="${myForm.*}">...</div>
<div th:if="${#fields.hasErrors('${myForm}')}">...</div>
<div th:if="${#fields.hasErrors('${myForm.date}')}">...</div>
<div th:if="${#fields.hasErrors('${myForm.*}')}">...</div>
<form th:object="${myForm}">
...
</form>
7.5 Rich error objects
Thymeleaf offers the possibility to obtain form error information in the form of beans (instead of mere strings), with the fieldName
(String), message
(String) and global
(boolean) attributes.
These errors can be obtained by means of the #fields.detailedErrors()
utility method:
<ul>
<li th:each="e : ${#fields.detailedErrors()}" th:class="${e.global}? globalerr : fielderr">
<span th:text="${e.global}? '*' : ${e.fieldName}">The field name</span> |
<span th:text="${e.message}">The error message</span>
</li>
</ul>
8 It’s still a Prototype!
Our application is ready now. But let’s have a second look at the .html
page we created…
One of the nicest consequences of working with Thymeleaf is that after all this functionality we have added to our HTML, we can still use it as a prototype (we say it is a Natural Template). Let’s open seedstartermng.html
directly in our browser without executing our application:
There it is! It’s not a working application, it’s not real data… but it is a perfectly valid prototype made up of perfectly displayable HTML code.
9 The Conversion Service
9.1 Configuration
As explained before, Thymeleaf can make use of a Conversion Service registered at the Application Context. Our application configuration class, by extending Spring’s own WebMvcConfigurerAdapter
helper, will automatically register such conversion service, which we can configure by adding the formatters that we need. Let’s see again what it looks like:
@Override
public void addFormatters(final FormatterRegistry registry) {
super.addFormatters(registry);
registry.addFormatter(varietyFormatter());
registry.addFormatter(dateFormatter());
}
@Bean
public VarietyFormatter varietyFormatter() {
return new VarietyFormatter();
}
@Bean
public DateFormatter dateFormatter() {
return new DateFormatter();
}
9.1 Double-brace syntax
The Conversion Service can be easily applied in order to convert/format any object into String. This is done by means of the double-brace expression syntax:
- For variable expressions:
${{...}}
- For selection expressions:
*{{...}}
So, for example, given an Integer-to-String converter that adds commas as a thousands separator, this:
<p th:text="${val}">...</p>
<p th:text="${{val}}">...</p>
…should result in:
<p>1234567890</p>
<p>1,234,567,890</p>
9.2 Use in forms
We saw before that every th:field
attribute will always apply the conversion service, so this:
<input type="text" th:field="*{datePlanted}" />
…is actually equivalent to:
<input type="text" th:field="*{{datePlanted}}" />
Note that, per requirement of Spring, this is the only scenario in which the Conversion Service is applied in expressions using single-brace syntax.
9.3 #conversions
utility object
The #conversions
expression utility object allows the manual execution of the Conversion Service wherever needed:
<p th:text="${'Val: ' + #conversions.convert(val,'String')}">...</p>
Syntax for this utility object:
#conversions.convert(Object,Class)
: converts the object to the specified class.#conversions.convert(Object,String)
: same as above, but specifying the target class as a String (note thejava.lang.
package can be ommitted).
10 Rendering Template Fragments
Thymeleaf offers the possibility to render only part of a template as the result of its execution: a fragment.
This can be a useful componentization tool. For example, it can be used at controllers that execute on AJAX calls, which might return markup fragments of a page that is already loaded at the browser (for updating a select, enabling/disabling buttons…).
Fragmentary rendering can be achieved by using Thymeleaf’s fragment specs: objects implementing the org.thymeleaf.fragment.IFragmentSpec
interface.
The most common of these implementations is org.thymeleaf.standard.fragment.StandardDOMSelectorFragmentSpec
, which allows specifying a fragment using a DOM Selector exactly like the ones used at th:include
or th:replace
.
10.1 Specifying fragments in view beans
View beans are beans of the org.thymeleaf.spring4.view.ThymeleafView
class declared at the application context (@Bean
declarations if you are using Java configuration). They allow the specification of fragments like this:
@Bean(name="content-part")
@Scope("prototype")
public ThymeleafView someViewBean() {
ThymeleafView view = new ThymeleafView("index"); // templateName = 'index'
view.setMarkupSelector("content");
return view;
}
Given the above bean definition, if our controller returns content-part
(the name of the above bean)…
@RequestMapping("/showContentPart")
public String showContentPart() {
...
return "content-part";
}
…thymeleaf will return only the content
fragment of the index
template – which location will probably be something like /WEB-INF/templates/index.html
, once prefix and suffix are applied. So the result will be completely equivalent to specifying index :: content
:
<!DOCTYPE html>
<html>
...
<body>
...
<div th:fragment="content">
Only this div will be rendered!
</div>
...
</body>
</html>
Note also that, thanks to the power of Thymeleaf Markup Selectors, we could select a fragment in a template without needing any th:fragment
attributes at all. Let’s use the id
attribute, for example:
@Bean(name="content-part")
@Scope("prototype")
public ThymeleafView someViewBean() {
ThymeleafView view = new ThymeleafView("index"); // templateName = 'index'
view.setMarkupSelector("#content");
return view;
}
…which will perfectly select:
<!DOCTYPE html>
<html>
...
<body>
...
<div id="content">
Only this div will be rendered!
</div>
...
</body>
</html>
10.2 Specifying fragments in controller return values
Instead of declaring view beans, fragments can be specified from the controllers themselves by using the syntax of fragment expressions. Just like in th:insert
or th:replace
attributes:
@RequestMapping("/showContentPart")
public String showContentPart() {
...
return "index :: content";
}
Of course, again the full power of DOM Selectors is available, so we could select our fragment based on standard HTML attributes, like id="content"
:
@RequestMapping("/showContentPart")
public String showContentPart() {
...
return "index :: #content";
}
And we can also use parameters, like:
@RequestMapping("/showContentPart")
public String showContentPart() {
...
return "index :: #content ('myvalue')";
}
11 Advanced Integration Features
11.1 Integration with RequestDataValueProcessor
Thymeleaf seamlessly integrates with Spring’s RequestDataValueProcessor
interface. This interface allows the interception of link URLs, form URLs and form field values before they are written to the markup result, as well as transparently adding hidden form fields that enable security features like e.g. protection agains CSRF (Cross-Site Request Forgery).
An implementation of RequestDataValueProcessor
can be easily configured at the Application Context. It needs to implement the org.springframework.web.servlet.support.RequestDataValueProcessor
interface and have requestDataValueProcessor
as a bean name:
@Bean
public RequestDataValueProcessor requestDataValueProcessor() {
return new MyRequestDataValueProcessor();
}
…and Thymeleaf will use it this way:
th:href
andth:src
callRequestDataValueProcessor.processUrl(...)
before rendering the URL.th:action
callsRequestDataValueProcessor.processAction(...)
before rendering the form’saction
attribute, and additionally it detects when this attribute is being applied on a<form>
tag —which should be the only place, anyway—, and in such case callsRequestDataValueProcessor.getExtraHiddenFields(...)
and adds the returned hidden fields just before the closing</form>
tag.th:value
callsRequestDataValueProcessor.processFormFieldValue(...)
for rendering the value it refers to, unless there is ath:field
present in the same tag (in which caseth:field
will take care).th:field
callsRequestDataValueProcessor.processFormFieldValue(...)
for rendering the value of the field it applies to (or the tag body if it is a<textarea>
).
Note there are very few scenarios in which you would need to explicitly implement
RequestDataValueProcessor
in your application. In most cases, this will be used automatically by security libraries you transparently use, like e.g. Spring Security’s CSRF support.
11.1 Building URIs to controllers
Since version 4.1, Spring allows the possibility to build links to annotated controllers directly from views, without the need to know the URIs these controllers are mapped to.
In Thymeleaf, this can be achieved by means of the #mvc.url(...)
expression object method, which allows the specification of controller methods by the capital letters of the controller class they are in, followed by the name of the method itself. This is equivalent to JSP’s spring:mvcUrl(...)
custom function.
For example, for:
public class ExampleController {
@RequestMapping("/data")
public String getData(Model model) { ... return "template" }
@RequestMapping("/data")
public String getDataParam(@RequestParam String type) { ... return "template" }
}
The following code will create a link to it:
<a th:href="${(#mvc.url('EC#getData')).build()}">Get Data Param</a>
<a th:href="${(#mvc.url('EC#getDataParam').arg(0,'internal')).build()}">Get Data Param</a>
You can read more about this mechanism at http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc-links-to-controllers-from-views
12 Spring WebFlow integration
12.1 Basic configuration
The Thymeleaf + Spring integration packages include integration with Spring WebFlow (2.3+).
WebFlow includes some AJAX capabilities for rendering fragments of the displayed page when specific events (transitions) are triggered, and in order to enable Thymeleaf to attend these AJAX requests, we will have to use a different ViewResolver
implementation, configured like this:
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.AjaxThymeleafViewResolver">
<property name="viewClass" value="org.thymeleaf.spring4.view.FlowAjaxThymeleafView" />
<property name="templateEngine" ref="templateEngine" />
</bean>
…and then this ViewResolver
can be configured at your WebFlow ViewFactoryCreator
like:
<bean id="mvcViewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="thymeleafViewResolver"/>
</bean>
From here on, you can specify Thymeleaf templates in your view-state’s:
<view-state id="detail" view="bookingDetail">
...
</view-state>
In the above example, bookingDetail
is a Thymeleaf template specified in the usual way, understandable by any of the Template Resolvers configured at the TemplateEngine
.
12.2 AJAX fragments in Spring WebFlow
Note that what is explained here is just the way to create AJAX fragments to be used with Spring WebFlow. If you are not using WebFlow, creating a Spring MVC controller that responds to an AJAX request and returns a chunk of HTML is as straightforward as creating any other template-returning controller, with the only exception that you would probably be returning a fragment like
"main :: admin"
from your controller method.
WebFlow allows the specification of fragments to be rendered via AJAX with <render>
tags, like this:
<view-state id="detail" view="bookingDetail">
<transition on="updateData">
<render fragments="hoteldata"/>
</transition>
</view-state>
These fragments (hoteldata
, in this case) can be a comma-separated list of fragments specified at the markup with th:fragment
:
<div id="data" th:fragment="hoteldata">
This is a content to be changed
</div>
Always remember that the specified fragments must have an id
attribute, so that the Spring JavaScript libraries running on the browser are capable of substituting the markup.
<render>
tags can also be specified using DOM selectors:
<view-state id="detail" view="bookingDetail">
<transition on="updateData">
<render fragments="[//div[@id='data']]"/>
</transition>
</view-state>
…and this will mean no th:fragment
is needed:
<div id="data">
This is a content to be changed
</div>
As for the code that triggers the updateData
transition, it looks like:
<script type="text/javascript"<EMAIL_ADDRESS><script type="text/javascript"<EMAIL_ADDRESS><script type="text/javascript"<EMAIL_ADDRESS>...
<form id="triggerform" method="post" action="">
<input type="submit" id="doUpdate" name="_eventId_updateData" value="Update now!" />
</form>
<script type="text/javascript">
Spring.addDecoration(
new Spring.AjaxEventDecoration({formId:'triggerform',elementId:'doUpdate',event:'onclick'}));
</script>


minerva-client.js
If this server is not running on your machine, all of the source code is available at ludios/Minerva.


NIXON A film review by Joan Ellis Copyright 1996 Nebbadoon Syndicate
"Nixon" is the best and worst of Oliver Stone. If it is an interesting chronicle of America's cardinal political scandal, it still smacks of a researcher so proud of his work that he can't bear to leave anything out. It's too damned long.
>From his White House bunker, Nixon tries to snuff out the Watergate brush fire by jettisoning his advisors in ascending order of importance. First, the break-in team: Hunt, Liddy, McCord, Martinez, Sturgis; next, White House staffers Erlichman, Haldeman, and Dean; then friend and attorney-general John Mitchell.
At the end, he is surrounded by players from the bench: the inept Ron Ziegler, the ambitious Al Haig, and the infamous Henry Kissinger, who can barely contain his glee at the possibility of being the hero who saves the country from a sick man. In the "Deep Throat" guessing game, it's worth noting that Kissinger is the one figure who needed two decades of secrecy in order to continue his career as international power broker.
The facts of Watergate were proven long ago and confirmed repeatedly by the testimony of the participants, leaving little for Oliver Stone to posit or prove. A sitting president committed at least 39 felonies, orchestrated a cover-up, lied profoundly, and taped himself in the act. When the Supreme Court ruled 8-0 that the president could not use executive privilege in a criminal case, the game was over.
Reaching for a purpose for his film, Stone decides to explore and explain Richard Nixon. He paints his portraits in the emotional, questionable brush strokes of psychohistory. Did Nixon really fuel himself with scotch?  Is it fair to hypothesize about the intimacy of the Nixon bedroom?
Stone tells us that the slights and snubs of childhood produced the paranoid star of the Watergate tapes. In the final hour, he hammers his point home by cutting his camera wildly through Nixon's visions in flailing excess that threatens to overwhelm the stark truth. This is melodrama where none is needed.
Anthony Hopkins, with his head seeming to grow from somewhere in his chest, catches the awkward stance and tension that informed Nixon's behavior. He has captured perfectly the sudden smile that burst from a dark scowl under pressure. Supported all the way by a strong cast, Hopkins turns in a performance that is an uncanny suggestion of Nixon's core.
As Nixon's wife, Joan Allen is every bit as enigmatic as the real Pat Nixon. She conveys beautifully the sense of the claustrophobic prison that surrounds her. The actress's compassion for Mrs. Nixon is palpable.
The drama of peeling away the layers of guilt until Nixon stands exposed needs no embellishment.  This is one story that did not need Oliver Stone.
Film Critic : JOAN ELLIS Word Count : 498 Studio : Hollywood Pictures Rating : R Running Time: 3h10m
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


{% extends '_base.html' %} {% load humanize %} {% block availability_nav_active %}active{% endblock %} {% block back %}
These are the availabilities and tags the client user {{ user_identifier }} has for your organization, {{ request.user.ablatoruser.organization.name }}.
Ablator can retrieve these pieces of information because you provided it with the unhashed user identifier string. Please note that a reverse lookup of these is not possible. The person behind the client user string might have other for other organizations that are not displayed to members of your organization.
| Flavor | Created At | Enabled | Actions |
|---|---|---|---|
| {{ obj.flavor.functionality.app.organization.slug }} {{ obj.flavor.functionality.app.slug }} {{ obj.flavor.functionality.slug }} {{ obj.flavor.slug }} | {{ obj.created_at }} ({{ obj.created_at|naturaltime }}) | {% if obj.is_enabled %} Yes {% else %} No {% endif %} | Edit |
| No Availablities for this user identifier. |