@NotNull @Min(18) private Integer age;
-
@NotNull
won't allow an empty value -
@Min(18)
won't allow if the age is less than 18 -
!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Getting Started: Handing Form Submission</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <h1>Form</h1> <form action="#" th:action="@{/greeting}" th:object="${greeting}" method="post"> <p>Id: <input type="text" th:field="*{id}" /></p> <p>Message: <input type="text" th:field="*{content}" /></p> <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p> </form> </body> </html> The
th:action="@{/greeting}"
expression directs the form to POST to the/greeting
endpoint, while theth:object="${greeting}"
expression declares the model object to use for collecting the form data. The two form fields, expressed withth:field="*{id}"
andth:field="*{content}"
, correspond to the fields in theGreeting
object above@EnableSchedulingpublic class ScheduledTasks { private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); @Scheduled(fixedRate = 5000) public void reportCurrentTime() { System.out.println("The time is now " + dateFormat.format(new Date())); } }
-
The key components that make this code perform scheduled tasks are the
@EnableScheduling
and@Scheduled
annotations.@EnableScheduling
ensures that a background task executor is created. Without it, nothing gets scheduled.You use
@Scheduled
to configure when a particular method is run.Note: This example uses
fixedRate
, which specifies the interval between method invocations measured from the start time of each invocation. There are other options, likefixedDelay
, which specifies the interval between invocations measured from the completion of the task. You can also use@Scheduled(cron=". . .")
expressions for more sophisticated task scheduling.http://localhost:8080/greeting?name=World"
@RequestParam(value="name",required=false,defaultValue="World")@Entity public class Customer { @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; private String firstName; private String lastName; private Customer() {} public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } @Override public String toString() { return String.format( "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } }
Here you have a
Customer
class with three attributes, theid
, thefirstName
, and thelastName
. You also have two constructors. The default constructor only exists for the sake of JPA. You won't use it directly, so it is designated asprivate
.The
Customer
class is annotated with@Entity
, indicating that it is a JPA entity. For lack of a@Table
annotation, it is assumed that this entity will be mapped to a table namedCustomer
.The
Customer
'sid
property is annotated with@Id
so that JPA will recognize it as the object's ID. Theid
property is also annotated with@GeneratedValue
to indicate that the ID should be generated automatically@EnableJpaRepositories public class Application { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(H2).build(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean(); lef.setDataSource(dataSource); lef.setJpaVendorAdapter(jpaVendorAdapter); lef.setPackagesToScan("hello"); return lef; } @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); hibernateJpaVendorAdapter.setShowSql(false); hibernateJpaVendorAdapter.setGenerateDdl(true); hibernateJpaVendorAdapter.setDatabase(Database.H2); return hibernateJpaVendorAdapter; } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); }
In the configuration, you need to add the
@EnableJpaRepositories
annotation. This annotation tells Spring Data JPA that it should seek out any interface that extendsorg.springframework.data.repository.Repository
and automatically generate an implementation. By extendingJpaRepository
, yourCustomerRepository
interface transitively extendsRepository
. Therefore, Spring Data JPA will find it and create an implementation for you.Most of the content in
Application
sets up several beans to support Spring Data JPA and the sample:- The
dataSource()
method defines aDataSource
bean, as an embedded database to which the objects are persisted. - The
entityManagerFactory()
method defines aLocalContainerEntityManagerFactoryBean
that is ultimately used to createLocalContainerEntityManagerFactory
a bean that implements theEntityManagerFactory
interface. It is the bean through which JPA operations will be performed. Note that this factory bean'spackagesToScan
property is set to look for entities in the package named "hello". This makes it possible to work with JPA without defining a "persistence.xml" file. - The
jpaVendorAdapter()
method defines a Hibernate-based JPA vendor adapter bean for use by theEntityManagerFactory
bean. - The
transactionManager()
method defines aJpaTransactionManager
bean for transactional persistence.
@Service
public class FacebookLookupService { RestTemplate restTemplate = new RestTemplate(); @Async public Future<Page> findPage(String page) throws InterruptedException { System.out.println("Looking up " + page); Page results = restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class); Thread.sleep(1000L); return new AsyncResult<Page>(results); } }
The class is marked with the
@Service
annotation, making it a candidate for Spring's component scanning to detect it and add it to the application context.The
findPage
method is flagged with Spring's@Async
annotation, indicating it will run on a separate thread. The method's return type isFuture<Page>
instead ofPage
, a requirement for any asynchronous service. This code uses the concrete implementation ofAsyncResult
to wrap the results of the Facebook query.@Configuration @EnableAsync @EnableAutoConfiguration @ComponentScan public class Application implements CommandLineRunner { @Autowired FacebookLookupService facebookLookupService; @Override public void run(String... args) throws Exception { // Start the clock long start = System.currentTimeMillis(); // Kick of multiple, asynchronous lookups Future<Page> page1 = facebookLookupService.findPage("GoPivotal"); Future<Page> page2 = facebookLookupService.findPage("CloudFoundry"); Future<Page> page3 = facebookLookupService.findPage("SpringFramework"); // Wait until they are all done while (!(page1.isDone() && page2.isDone() && page3.isDone())) { Thread.sleep(10); //millisecond pause between each check } // Print results, including elapsed time System.out.println("Elapsed time: " + (System.currentTimeMillis() - start)); System.out.println(page1.get()); System.out.println(page2.get()); System.out.println(page3.get()); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
The
@EnableAsync
annotation switches on Spring's ability to run@Async
methods in a background thread pool.The
@EnableAutoConfiguration
annotation switches on reasonable default behaviors based on the content of your classpath. For example, it looks for any class that implements theCommandLineRunner
interface and invokes itsrun()
method. In this case, it runs the demo code for this guide.public class HelloController { @RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; } }
@RestController
combines@Controller
and@ResponseBody
, two annotations that results in web requests returning data rather than a viewpublic class FacebookLookupService { RestTemplate restTemplate = new RestTemplate(); @Cacheable("hello") public Page findPage(String page) { return restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class); } }
@Cacheable("hello")
. Spring's caching abstraction intercepts the call tofindPage
to check whether it's already been called. If so, Spring's caching abstraction returns the cached copy. Otherwise, it proceeds to invoke the method, store the response in the cache, and then return the results to the caller. - The