Skip to content
Permalink
Browse files

[#979] Docs: Fixed typos

  • Loading branch information...
sant0s authored and Peter Hilton (Lunatech) committed Jul 17, 2011
1 parent f94a3fc commit 5126a4732b7363a62b6b94ef910f33d33146278e
@@ -41,7 +41,7 @@ The @play new@ command creates a new directory @helloworld/@ and populates it wi

@public/@ contains all the publicly available resources, which includes JavaScript, stylesheets and images directories.

@test/@ contains all the application tests. Tests are either written either as Java JUnit tests or as Selenium tests.
@test/@ contains all the application tests. Tests are written either as Java JUnit tests or as Selenium tests.

p(note). Because **Play uses UTF-8** as single encoding, it's very important that all text files hosted in these directories are encoded using this charset. Make sure to configure your text editor accordingly.

@@ -285,7 +285,7 @@ bc. *{ You can use plain selenium command using the selenium tag }*
assertNotTitle('Application error')
#{/selenium}

This test should run without any problem with the application for now. It just open the home page and check that the page content does not contain the ‘Application error’ text.
This test should run without any problem with the application for now. It just opens the home page and checks that the page content does not contain the ‘Application error’ text.

Let’s write a test for our application. Edit the test content:

@@ -294,7 +294,7 @@ bc. #{selenium}
open('/')
assertNotTitle('Application error')

// Check that it is the form
// Check that it is the Hello World application
assertTextPresent('The Hello world app.')

// Submit the form
@@ -62,7 +62,7 @@ The @play new@ command creates a new directory @yabe/@ and populates it with a s

@public/@ contains all the publicly available resources, which includes JavaScript files, stylesheets and images directories.

@test/@ contains all the application tests. Tests are either written either as Java JUnit tests or as Selenium tests.
@test/@ contains all the application tests. Tests are written either as Java JUnit tests or as Selenium tests.

p(note). Because **Play uses UTF-8** as single encoding, it’s very important that all text files hosted in these directories are encoded using this charset. Make sure to configure your text editor accordingly.

@@ -172,7 +172,7 @@ You can remove this useless line, and now edit the @yabe/app/views/Application/i
bc. #{extends 'main.html' /}
#{set title:'Home' /}

<h1>A blog will be there</h1>
<h1>A blog will be here</h1>

Like for Java code changes, just refresh the page in the browser to see the modification.

@@ -216,7 +216,7 @@ $ bzr ignore logs
Now we can commit our first blog engine version:

bc. $ bzr add
$ bzr commit -m "YABE inital version"
$ bzr commit -m "YABE initial version"

h3. <a name="git">Git</a>

@@ -8,7 +8,7 @@ h2. <a name="controller">Testing the controller part</a>

Play gives you a way to test directly the application’s controller part using JUnit. We call these tests **‘Functional tests’**. This is because we want to test the web application’s complete functionality.

Basically a functional test calls the Play @ActionInvoker@ directly, simulating an HTTP request. So we give an HTTP method, an URI and HTTP parameters. Play then routes the request, invokes the corresponding action and sends you back the filled response. You can then analyze it to check that the response content is like you expected.
Basically a functional test calls the Play @ActionInvoker@ directly, simulating an HTTP request. So we give an HTTP method, a URI and HTTP parameters. Play then routes the request, invokes the corresponding action and sends you back the filled response. You can then analyze it to check that the response content is like you expected.

Let’s write a first functional test. Open the @yabe/test/ApplicationTest.java@ unit test:

@@ -55,7 +55,7 @@ These kinds of JUnit based **‘Functional tests’** are still useful, typicall

h2. <a name="selenium">Writing Selenium tests</a>

"Selenium":http://seleniumhq.org is a testing tool specifically for testing web applications. The cool things here is that Selenium allows to run the test suite directly in any existing browser. As it does not use any ‘browser simulator’, you can be sure that you’re testing what your users will use.
"Selenium":http://seleniumhq.org is a testing tool specifically for testing web applications. The cool thing here is that Selenium allows to run the test suite directly in any existing browser. As it does not use any ‘browser simulator’, you can be sure that you’re testing what your users will use.

A Selenium test suite is typically written as an HTML file. The HTML syntax required by Selenium is a little tedious to write (formatted using an HTML table element). The good news is that Play helps you generate it using the Play template engine and a set of tags that support a simplified syntax for Selenium scenarios. An interesting side effect of using templates is that your are not tied to ‘static scenarios’ any more and you can use the power of Play templates (looping, conditional blocks) to write more complicated tests.

@@ -74,7 +74,7 @@ bc. *{ You can use plain Selenium commands using the selenium tag }*

This test should run without any problem with the yabe application. It just opens the home page and checks that the page content does not contain the ‘Application error’ text.

However like any complex test, you need to set-up a set of well-known data before navigating the application and testing it. We will of course reuse the fixture concept and the @yabe/test/data.yml@ file that we’ve used before. To import this data set before the test suite, just use the @#{fixtures /}@ tag:
However like any complex test, you need to set-up a set of well-known data before navigating the application and testing it. We will of course reuse the fixture concept and the @yabe/test/data.yml@ file that we’ve used before. To import this data set before the test suite, just use the @#{fixture /}@ tag:

bc. #{fixture delete:'all', load:'data.yml' /}

@@ -38,7 +38,7 @@ Change the @jpa.ddl@ configuration key:

bc. %server01.jpa.ddl=update

However it’s kind of unpredictable, and running magical things on a production database is never a good thing. So you should always have a backup before a new deployement. If you don't want that hibernate update your database, change the @jpa.ddl@ configuration key to validate:
However it’s kind of unpredictable, and running magical things on a production database is never a good thing. So you should always have a backup before a new deployement. If you don't want Hibernate to update your database, change the @jpa.ddl@ configuration key to @validate@:

bc. %server01.jpa.ddl=validate

@@ -75,4 +75,4 @@ There are still more features we haven’t explored yet, especially related to W

If you are convinced that Play will help you save time for your next Java web application, you’re now ready to start. And don’t hesitate to ask us any question on the "Play Google Group":http://groups.google.com/group/play-framework.

**Thank you!**
**Thank you!**
@@ -1,14 +1,14 @@
h1. Internationalisation and localisation

Having built our fully-functional blog engine, we will now consider an optional extra: web application internationalization and language localisation. Although we could have done this from the start, it is more realistic to build the first version of an application in a single language, and add multiple languages later.
Having built our fully-functional blog engine, we will now consider an optional extra: web application internationalisation and language localisation. Although we could have done this from the start, it is more realistic to build the first version of an application in a single language, and add multiple languages later.

h2. <a>Internationalisation and localisation</a>

There are two steps to perform: "internationalisation":http://en.wikipedia.org/wiki/Internationalization_and_localization and "localisation":http://en.wikipedia.org/wiki/Language_localisation. Both are mostly about text.

*Internationalisation*, in programming terms, is a refactoring to remove locale-specific code from the application code. In a web application, this is almost entirely about replacing user-interface text in view templates with references to messages. It also includes formatting non-text data types: dates, currency and other numbers.

*Localisation* is making a locale-specific version of an application. If the application is internationlised, this means having one or more selectable locale-specific versions. In a web application, this localisation is mostly about translating the user-interface text into the chosen natural language. Language selection is typically a combination of language preferences set in the web browser, and a language selection user-interface in the application itself.
*Localisation* is making a locale-specific version of an application. If the application is internationalised, this means having one or more selectable locale-specific versions. In a web application, this localisation is mostly about translating the user-interface text into the chosen natural language. Language selection is typically a combination of language preferences set in the web browser, and a language selection user-interface in the application itself.

In practice, the two steps go together: you both internationalise and localise one part of the application at a time.

@@ -126,7 +126,7 @@ You will notice that this does not change the rounded purple navigation links:

!images/guide12-2!

Those are defined @views/admin.html@ which you can internationalise to use the same localisations simply by surrounding the existing text with @&{'…'}@ as follows:
Those are defined in @views/admin.html@ which you can internationalise to use the same localisations simply by surrounding the existing text with @&{'…'}@ as follows:

bc. <a href="@{Posts.list()}">&{'Posts'}</a>
@@ -169,7 +169,7 @@ Note that we have to use @messages.get@ to look up the localised singular and pl

h2. <a>Play module localisation</a>

Play module localisation works the same was as localisation within your application. This application uses the CRUD and Secure modules, which means that we must localise the messages in @play/modules/crud/conf/messages@ and @play/modules/secure/conf/messages@ that our application uses.
Play module localisation works the same way as localisation within your application. This application uses the CRUD and Secure modules, which means that we must localise the messages in @play/modules/crud/conf/messages@ and @play/modules/secure/conf/messages@ that our application uses.

In @conf/messages.nl@

@@ -276,7 +276,7 @@ Of course, once you have done this it is also a good idea to contribute the loca

h2. <a>Special cases</a>

When you are localising a web application, there are a few special cases that be awkward to implement if you are using a component-based web application framework, such as JavaServer Faces:
When you are localising a web application, there are a few special cases that can be awkward to implement if you are using a component-based web application framework, such as JavaServer Faces:

# <span>Parameterised message used in an attribute value</span>
# <span>Formatted message parameter</span>
@@ -292,17 +292,17 @@ This is a problem in JSF, because you would normally use an XML tag to perform t

bc. <a href="@{Application.show(_post.id)}" title="&{'views.tags.display.author', _post.author.fullname}">

The second case is when you want to format a value, such as a date, for use as a message parameter in a phrase like @By Bob on 2009-06-14@. Again, the problem in JSF is caused by having to an XML tag to format the value, while needing to be able to use the result in an XML attribute value. In Play the formatting extensions do not get in the way of the message parameter syntax, so you can do:
The second case is when you want to format a value, such as a date, for use as a message parameter in a phrase like @By Bob on 2009-06-14@. Again, the problem in JSF is caused by having to use an XML tag to format the value, while needing to be able to use the result in an XML attribute value. In Play the formatting extensions do not get in the way of the message parameter syntax, so you can do:

bc. <span>&{'views.tags.display.author', _post.author.fullname, comment.postedAt.format('yyyy-MM-dd')}"}</span>

You can, of course, localise the format pattern as well:

bc. <span>&{'views.tags.display.author', _post.author.fullname, comment.postedAt.format(messages.get('views.dateFormat'))}"}</span>

The third case typically occurs when you want part of a localised message to be a hyperlink, as in the message <code><u>Log in</u> to write something</code>. This is a problem in JSF because the hyperlink is a JSF component that is rendered in a way that means the link's mark-up cannot be in the message file. Play on the other hand, lets you use plain HTML in your templates, so you can just put the mark-up in your message with a parameter for the URL:
The third case typically occurs when you want part of a localised message to be a hyperlink, as in the message <code><u>Log in</u> to write something</code>. This is a problem in JSF because the hyperlink is a JSF component that is rendered in a way that means the link's mark-up cannot be in the message file. Play, on the other hand, lets you use plain HTML in your templates, so you can just put the mark-up in your message with a parameter for the URL:

bc. logIn = <a href="%s">Log in</a> to write something
bc. logIn = <a href="%s">Log in</a> to write something

bc. &{'logIn', '/admin'}

@@ -1,4 +1,4 @@
h1. A first iteration for the data model
h1. A first iteration of the data model

Here we will start to write the model for our blog engine.

@@ -209,7 +209,7 @@ public void createPost() {
assertNotNull(firstPost.postedAt);
}

p(note). **Don’t forget** to import the @java.util.List@ or will get a compilation error.
p(note). **Don’t forget** to import the @java.util.List@ or you will get a compilation error.

h2. <a>Adding Comments</a>

@@ -295,7 +295,7 @@ public Post(User author, String title, String content) {
}
...

Note how we have used the @mappedBy@ attribute to tell JPA that the @Comment@ class’s post field maintains the relationship. When you define a bi-directional relation with JPA it is very important to tell it which side will maintain the relationship. In this case, since the @Comments@ belong to the @Post@, it’s better that the @Comment@ class maintains the relationship.
Note how we have used the @mappedBy@ attribute to tell JPA that the @Comment@ class’ post field maintains the relationship. When you define a bi-directional relation with JPA it is very important to tell it which side will maintain the relationship. In this case, since the @Comments@ belong to the @Post@, it’s better that the @Comment@ class maintains the relationship.

We have set the @cascade@ property to tell JPA that we want @Post@ deletion be cascaded to @comments@. This way, if you delete a post, all related comments will be deleted as well.

@@ -36,7 +36,7 @@ bc. …
</h2>

You can new refresh the home page, and click a post title to display the post.
You can now refresh the home page, and click a post title to display the post.

!images/guide4-0!

@@ -221,7 +221,7 @@ bc. public static void postComment(Long postId, @Required String author, @Requir
show(postId);
}

and display the success message in @show.html@ if present (add it at the top the page):
and display the success message in @show.html@ if present (add it at the top of the page):

bc. …
#{if flash.success}
@@ -39,7 +39,7 @@ Of course we could just put the text to the user session at the image generation

**Second**, remember that Play is a **stateless** framework. We want to manage things in a purely stateless way. Typically, what happens if a user simultaneously opens two different blog pages with two different captcha images? We have to track the captcha code for each form.

So to resolve the problem we need two things. We will store the captcha secret key on the server side. Because it is transient data we can easily use the Play **Cache**. Moreover because cached data have a limited life time it will add one more security mechanism (let’s say that a captcha code will be available for only 10mn). Then to resolve the code later we need to generate a **unique ID**. This unique ID will be added to each form as an hidden field and implicitely references a generated captcha code.
So to resolve the problem we need two things. We will store the captcha secret key on the server side. Because it is transient data we can easily use the Play **Cache**. Moreover because cached data have a limited life time it will add one more security mechanism (let’s say that a captcha code will be available for only 10mn). Then to resolve the code later we need to generate a **unique ID**. This unique ID will be added to each form as an hidden field and implicitly references a generated captcha code.

This way we elegantly solve our state problem.

@@ -254,7 +254,7 @@ Do the same for the @Tags@, @Comments@ and @Users@ controllers. Now try to log o

h2. <a>Customizing the CRUD layout</a>

That’s fun but when we go to the CRUD part of the administration area, we lose the administration layout. That’s because the CRUD module provides it own layout. But we can of course override it. Use this Play command:
That’s fun but when we go to the CRUD part of the administration area, we lose the administration layout. That’s because the CRUD module provides its own layout. But we can of course override it. Use this Play command:

bc. play crud:ov --layout

@@ -228,7 +228,7 @@ bc. #{extends 'admin.html' /}

#{/form}

As you can see we have updated the form destination action to add the post ID as the first action parameter if it exists. So when the post has an id field set (meaning that the post already exists in the system), it will be sent the the @Admin.save@ action.
As you can see we have updated the form destination action to add the post ID as the first action parameter if it exists. So when the post has an id field set (meaning that the post already exists in the system), it will be sent to the @Admin.save@ action.

Now we can change the @save()@ method a little to handle both creation and editing cases:

@@ -262,9 +262,9 @@ bc. public static void save(Long id, String title, String content, String tags)
index();
}

And for better URL we will use the same trick as before, by adding a new preferred route if an @id@ parameter exist:
And for better URL we will use the same trick as before, by adding a new preferred route if an @id@ parameter exists:

bc. POST /admin/myPosts/{id} Admin.save
bc. POST /admin/myPosts/{id} Admin.save
POST /admin/new Admin.save

That’s done! Now we’re using the same action for both creating new blog posts and editing old ones, and the administration area is finished!
@@ -84,7 +84,7 @@ The expression language used by the play template engine is "Groovy":http://groo

h2. <a>JPA on steroids</a>

The Java Persistence API (JPA) is the cleanest object-relational mapping ORM) API available for Java. If you already know it you will be amazed how much simpler it becomes with Play. With nothing to configure, Play will automatically start the JPA Entity Manager and magically synchronize it while the code is reloaded.
The Java Persistence API (JPA) is the cleanest object-relational mapping (ORM) API available for Java. If you already know it you will be amazed how much simpler it becomes with Play. With nothing to configure, Play will automatically start the JPA Entity Manager and magically synchronize it while the code is reloaded.

Moreover if you use the provided @play.db.jpa.Model@ superclass it will help make your code prettier. Have a look:

0 comments on commit 5126a47

Please sign in to comment.
You can’t perform that action at this time.