2007-09-20

SimpleTapestry 5 CRUD application - Step 08, Simple authentication

To be updated.
I'd like to make some page "protected" i.e. if a user hasn't been logged in then such a page must not be displayed. The solution was found here:

T5 - Authentication filter

T5:Login and session

So, I added one new page class (abstract), LoginProtected it should serve as a base for all "protected" pages:

//incomplete listing
public abstract class LoginProtected {
@ApplicationState
private SessionData _session;

Object onActivate() {
if(!_session.isSessionExists()){
return "Login";
}
return null;
}


SessionData is a "value" object to store userName and sessionExists flag between pages, so if a session doesn't exist then user will be redirected to Login page.

Also, I changed the Home page, now it extends LoginProtected:
public class Home extends LoginProtected {

Another change - Login.java, new private variable _session was added, see the code.

So, now, if a user tries to open /home page without logging in , the navigation will go to the Login page.

8. Step 08, Simple authentication
7. SimpleTapestry 5 CRUD application -Step 07, Cancel button, variant 1.
6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.




2007-07-21

SimpleTapestry 5 CRUD application - renaming (refactoring) and migration to 5.0.5.

Migration from T5.0.4 to T5.0.5:

Please archive your project before the action!

1. pom.xml, find the line
<tapestry-release-version>5.0.4</tapestry-release-version>
and cnange it to
<tapestry-release-version>5.0.5

2. Right click menu->Maven2->Update Source Folder;
3. After 2. the project in Eclipse was shown as full or errors ->Open project's properties and add all libraries into classpath (Java Build Path). Remember about javax.servlet.jar (Step 06);
4. After 3. - the were still several errors in the project, org.apache.tapestry... were not resolved, I tried "dance with a tambourine" approach: Maven2 Clean/Build commands etc but it didn't work. So, had to build a new T5 quick-start project with help of

mvn archetype:create -DarchetypeGroupId=org.apache.tapestry -DarchetypeArtifactId=quickstart -DarchetypeVersion=5.0.5 -DgroupId=org.example -DartifactId=myapp -DpackageName=org.example.myapp -Dversion=1.0.0-SNAPSHOT

And that didn't help also... .
So, I just deleted the project from Eclipse and from disk.
5. Restored the project from the archive and imported in in Eclipse again, repeated 1,2,3 and now it even compiles!

I also renamed the project from TSA504 to just TSA.

2007-06-19

SimpleTapestry 5 CRUD application -Step 07, Cancel button, variant 1.

Added "Cancel" button on AddNew page:

1.Turned off client validation:
AddNew.html, <form t:id="regform" t:clientValidation="false">
2.
AddNew.html, added <input t:type="submit" value="Cancel" t:id="Cancel"/>
3. AddNew.java, added
private String _pageToReturn;
------------------------------------
String onSuccess() {
if (_pageToReturn!=null){return _pageToReturn;}...
------------------------------------
void onSelectedFromCancel(){
_regform.clearErrors();
_pageToReturn = "Start";
}

Of course, there should be a better way... Let me search or drop a ray of light, if you have one :).

8. Step 08, Simple authentication

7. SimpleTapestry 5 CRUD application -Step 07, Cancel button, variant 1.
6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.

2007-06-11

SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.

Added several modifications into the files:

1. Home page grid doesn't show the PWD column any more (but BeanEditForm example page (UpdateExisting) does), it's made by using/correcting the "model" attribute of "Grid" in Home.java:

//Inspired by http://tapestry.apache.org/tapestry5/tapestry-core/guide/beaneditform.html
void pageLoaded()
{
_model = _beanModelSource.create(TUser.class, true, _resources);
_model.remove("password");
}
and Home.html

<table t:type="grid" rowsPerPage="5" row="tUser" source="usersList" model="model">

2.
I renamed Registration page to UpdateExisting, it's now used for displaying and editing data of existing users - from Home page click a user name in the grid to get his/her details available for editing. onActivate()+ onPassivate() approach is used:

UpdateExisting.java


Home.html changes:
<table t:type="grid" rowsPerPage="5" row="tUser" source="usersList" model="model">
<t:parameter name="usernameCell">
<a t:type="PageLink" t:page="UpdateExisting" context="tUser.userName">${tUser.userName}</a>
</t:parameter>
</table>

3. UpdateExisting.html was changed to show "password" field values as PasswordFied type (i.e. hidden by *****):

<form t:type="BeanEditForm" object="tUser" submitLabel="Update">
<t:parameter name="password">
<t:label for="password"/>
<t:passwordfield t:id="password" value="tUser.password"/>
</t:parameter>
</form>

4. Added UTF-8 support, thanks to HowTo. A probable issue here is AppModule.java, IDE complains on new UTF_8 code. It was resolved by adding \jetty-5.1.7\lib\javax.servlet.jar into the classpath.



7. SimpleTapestry 5 CRUD application -Step 07, Cancel button, variant 1.
6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.

2007-05-29

SimpleTapestry 5 CRUD application - Step XY - BeanEditForm and Grid

I've modified UserAuthenticator (added a method for getting users list,

public
List getTUsersList();


and it's implementation into
UserAuthenticatorImpl

@SuppressWarnings("unchecked") //to avoid IDE's complaints)
public List getTUsersList() {

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from TUser").list();
session.getTransaction().commit();
return result;
}

)

added 2 new pages,

Registration (BeanEditForm example, ScreenCast #4)
the page duplicates in fact AddNew page functionality, was added just as an example of different approaches
Registration.html (submitLabel="Create" is not the same as in the screencast )and Registration.java

and

Home (Grid example, ScreenCast #5). The page purpose is a) to show an example of Grid component usage; b) The grid on the page must display all the registered users (that's why
getTUsersList() was added).

Home.html
I used
<t:parameter name="passwordCell">
*****
</t:parameter>

to hide
"password" column values (see next post for other way).

public class Home { @Inject private UserAuthenticator _authenticatior;
public List getUsersList()
{
return _authenticatior.getTUsersList(); }
}


Now, after successful login navigation goes to the Home (which displays existing users list):


There are still a lot of question and things-to-be-improved... .
7. SimpleTapestry 5 CRUD application -Step 07, Cancel button, variant 1.
6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.



2007-05-24

SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.

1.Create new class package = org.example.TSA504.hibernate, name=HibernateUtil
2. Add the hibernate3.jar (I used Hibernate Core 3.2.4.SP1 ) into the project's
Java Build Path.
3. I used Hibernate on-line documentation for constructing the class
and several samples from «unknown java developers», so contact me if you think I violate someone's copyright.
4. Now, I'm using PostgreSQL 8.2 and Hibernate annotations in order to «auto-create» DB table(s), so the
hiberbate.cfg.xml file might looks like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost/TSA</property>
<property name="connection.username">postgre</property>
<property name="connection.password">postgre</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">10</property>
<property name="jdbc.use_streams_for_binary">true</property>
<property name="transaction.flush_before_completion">true</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="org.example.TSA504.beans.TUser"/>
</session-factory>
</hibernate-configuration>


I also have TSA DB already created (with zero tables at the moment, it means that I simly had created new DB and nothing more ) and I have postgre user among DB's Login Roles.

Note, the line

<property name="hbm2ddl.auto">create</property>

provides DB tables "auto-creation" (be means of Hibernate annotations). If you leave the line then every time you use a page linked to a table that table will be created again (and all previous data will gone away).
So, when all tables which you need were created - just comment the line.


(Another approach is to use (as it was pointed out by experienced Java-devs)
<property name="hibernate.hbm2ddl.auto">update</property>
but I haven't tried that yet)

5.Place hiberbate.cfg.xml in TSA504\src\main\resources\.
6.Add postgresql-8.1-409.jdbc3.jar library to the project.
7.
Let's tweak UserAuthenticator interface , add two new methods:

public
TUser getTUserByUserName(String userName);
public boolean addNewTUser(TUser tUser);

8.
We need to have just added methods implementation and to have isValid() method modified, so I suggest to have following UserAuthenticatorImpl.java (if you have a better implementation – I'd like to be taught ).
9. Except getting a «user» from DB, it's quite good to have ability to add new entries into DB. Try this – create new html file \TSA504\src\main\webapp\WEB-INF\AddNew.html and new page class org.example.TSA504.pages.AddNew.java (very similar to Login.java) . Also, modify our Start.html, add

<br/>
[<a t:type="PageLink" page="AddNew">Add New </a>]

10. Well, let's try to use all that - run the jetty and open http://localhost:8080/TSA504/start, click the AddNew link, fill in the form, submit and ... I got:

java.lang.ExceptionInInitializerError exception java.lang.NoClassDefFoundError: org/dom4j/DocumentException

There are, probably, no «expected» libraries ... so, I added all (just in case...) from hibernate-3.2\lib\ and
hibernate-annotations-3.3.0.GA\lib\hibernate-commons-annotations.jar into the project class-path.

Please remember also about ejb3-persistence.jar (if you'd like to use Hibernate annotations), see the previous post.

11. ->jetty -> http://localhost:8080/TSA504/start, -> the AddNew link, fill in the form, submit and ... well, it works at least for the 1-st time and new table is added into the DB... . There is a lot to be changed and tweaked here, so - let me learn a bit more about Java before continuation ;).

6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.



2007-05-17

SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.

A small lyrical digression: I'd like to follow the MVC pattern in creating the application and it's time now to add some "model" or "bean" code into the project.

After the Step 02 we already have a login page and a service for user authentication, but we still have no «user», so :
  1. Create a new class, package = org.example.TSA504.beans, name=TUser, implements Serializable, and generate the serialVersionUID field.

  2. Now, I'd like to use Hibernate with annotations and avoid boring .hbm files writing/generating, so we need to add some libraries into the project. Create a new folder TSA504\lib\ , find and copy ejb3-persistence.jar and hibernate-annotations.jar into it ( I found the files in hibernate-entitymanager-3.3.1.GA\lib\).

  3. After that, add the libraries into the project's Java Build Path:

  4. Let's start to «create» our user bean:

@Entity
@Table(name = "TUSER")
public class TUser implements Serializable {
private static final long serialVersionUID = 7769115993193444629L;
protected long id;
protected String userName;
protected String firstName;
protected String MI;
protected String lastName;
protected String email;
protected String password;
...
}

So, as you see, it's quite a simple class, you can find the listing here. Pay attention to the imports.

  1. The bean implements the Serializable interface, so we have to write equals(), hashCode() and toString() methods. Have to say honestly, I've been impressed by Appfuse project, so I've picked up a bit from there. Note, toString() realization needs commons-lang-2.3.jar, so don't forget to add the library to the project.


    6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
    5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
    4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
    3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
    2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
    1. SimpleTapestry 5 CRUD application -Step 01.

2007-05-10

SimpleTapestry 5 CRUD application - migration from 5.0.3 to 5.0.4.

Just has moved from 5.0.3 to 5.0.4, use

mvn archetype:create -DarchetypeGroupId=org.apache.tapestry -DarchetypeArtifactId=quickstart -DarchetypeVersion=5.0.4 -DgroupId=org.example -DartifactId=TSA504 -DpackageName=org.example.TSA504 -Dversion=1.0.0-SNAPSHOT

to get the new project.

After the downloading you have to modify pom.xml – change

<tapestry-release-version>5.0.3</tapestry-release-version>

to

<tapestry-release-version>5.0.4-SNAPSHOT</tapestry-release-version>

and update Maven dependencies (I used Maven plugin for eclipse).

Now, repeat Step 01 and Step 02 for that new 5.0.4 project. All should be fine, just don't forget to change 503s to 504s.


P.S. Actually, Tapestry-User mail-list also suggests another "digit" - changing 5.0.4-SNAPSHOT just to 5.0.4 - and it works.


2007-05-09

SimpleTapestry 5 CRUD application -Step 02, adding a service.

Assuming Step 01, let's change Login page class a bit. Find and uncomment following lines with the «// Don't need this for now.»:

@Inject
private UserAuthenticator _authenticator;

and

if (!_authenticator.isValid(_userName, _password))

Then, just delete the line

if (!_userName.equals(_password))

So, here is the result , our new Login.java.

At this moment we have UserAuthenticator undefined, so let's create it – select NEW->Interface ->package = org.example.TSA503.services.interfaces, name= UserAuthenticator . The interface body is simple:

public interface UserAuthenticator {
public
boolean isValid(String userName, String pwd);
}

Now, we have to create implementation of the interface, UserAuthenticatorImpl class – NEW-Class->package=org.example.TSA503.services, name=UserAuthenticatorImpl , implements UserAuthenticator of course.

The code is also simple:

public class UserAuthenticatorImpl implements UserAuthenticator {
public boolean isValid(String userName, String pwd) {
if (userName.equalsIgnoreCase(pwd)){
return true;
}
return false;
}
}

Open your Login.java and add such an import: org.example.TSA503.services.interfaces.UserAuthenticator

Save the project and run it on jetty, open the link http://localhost:8080/TSA503/login and ...

something wrong, just because

java.lang.ClassNotFoundException: caught an exception while obtaining a class file for org.example.TSA503.pages.Login

can't be a Login page. So, let's do some additional work and notify Tapestry about our UserAuthenticator service, open /TSA503/src/main/java/org/example/TSA503/services/AppModule.java and append following to it:

public static UserAuthenticator buildUserAuthenticator()
{
return new UserAuthenticatorImpl();
}

Also, add such an import:

import org.example.TSA503.services.interfaces.UserAuthenticator;

And now - run the jetty again and open http://localhost:8080/TSA503/login - it must be fine at this time, so you can «test» the page, who knows, it may contains a lot of bugs.


6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.

2007-02-26

SimpleTapestry 5 CRUD application -Step 01.

Hello all,

couple words about this post and what's all this for and about.

I'm totally new to Java, sometime ago one «unknown java developer» told me a lot of Java and wonders of Tapestry 5, so I've decided to pick some knowledge up.

My first impression of Java world was just a shock, too many ways and variants, too many «TLAs» («Three letter acronyms», see the t5-tutorial ). I've suffered of lack of simple and clear tutorials for «newcomers» - only all those «it's very simple», «it's so clear that I won't explain» and so on. So, the purpose of this particular post is to share some «new to Tapestry 5» experience.

First, I suggest to read the t5-tutorial (it's small and incomplete but still) and have a look at ApacheTapestry pages (screencasts are very helpful at the beginning).

Second, I'd like to write a very simple t5 web-application, e.g. only several pages like Login, Home, Add/Edit User, sort of CRUD functionality. I found some information about user authentication in Tapestry 4 and some sample code on tapestry-core pages , think it might help.

For the start, we need to install all the tools we need. Don't forget to add JDK and maven location to your PATH variable (for Windows users only, Linux and MacOS have their own settings).

At the moment current T5's version is 5.0.4 but it has some issues with downloading etc, so. Let's use 5.0.3. Create a tapestry simple project (see the screencasts and tapestry-quick start page ). Name the new application as org.example.TSA503 (Tapestry Simple Application, one more TLA ;) )- run following from the command line:

mvn archetype:create -DarchetypeGroupId=org.apache.tapestry -DarchetypeArtifactId=quickstart -DarchetypeVersion=5.0.3 -DgroupId=org.example -DartifactId=TSA503 -DpackageName=org.example.TSA503 -Dversion=1.0.0-SNAPSHOT

Hope, you will see BUILD SUCCESSFUL.


Open and run generated project in eclipse . Don't be too confused, the 5.0.3 quickstart project contains several "errors" -find the /TSA503/src/main/java/org/example/TSA503/services/AppModule.java file, find and remove following lines:

import org.apache.tapestry.ioc.annotations.Contribute;

import org.apache.tapestry.ioc.annotations.Id;

@Id("app")

@Contribute("tapestry.ioc.ApplicationDefaults")

@Contribute("tapestry.RequestHandler")

Now, you can play a bit with the Start page to see some features shown in the screencasts.


Create new HTML file in /TSA503/src/main/webapp/WEB-INF/ - Login.html

Navigate to the Input validation page , copy login page html code from «Configuring Fields and Labels» and paste it into your new /WEB-INF/Login.html.

After that, create a new class, the login page class, in /TSA503/src/main/java/org/example/TSA503/pages/ - Login.java. Have a look at the class Login at the «Storing Data Between Requests» section, we will use it a bit later just for now Login.java might look like this.

Save all, run the application on jetty and open http://localhost:8080/TSA503/login in a browser. You'll see your Login page, now you can test it a little, how does the validation work, what's the navigation flow etc.

After all above, I suggest to add several small modifications to the application. - don't stop the server, find the Start page template in /TSA503/src/main/webapp/WEB-INF/Start.html, find the

[<a t:type="PageLink" page="Start">refresh </a>]

there and add the following:

<br/>
[<a t:type="PageLink" page="Login">Login </a >]

to get the:

[<a t:type="PageLink" page="Start">refresh </a>]
<br/>
[<a t:type="PageLink" page="Login">Login </a>]

Open http://localhost:8080/TSA503/start in your browser and see the changes, now you can get your Login page directly from the Start page.

So, the first step is very simple, it's only shows the very basics, but I hope it can be useful for anybody who wants to know more.

Constructive comments and corrections are welcomed :).

Next step - adding the UserAuthenticator service into the project.


6. SimpleTapestry 5 CRUD application -Step 06, tweaking a grid a bit.
5. Simple Tapestry 5 CRUD application - BeanEditForm and Grid screencasts aprobation.
4. SimpleTapestry 5 CRUD application -Step 04 Adding some basic Hibernate features into the project.
3. SimpleTapestry 5 CRUD application -Step 03, "user" bean creation.
2. SimpleTapestry 5 CRUD application -Step 02, adding a service.
1. SimpleTapestry 5 CRUD application -Step 01.