You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Apache Wiki <wi...@apache.org> on 2007/11/16 23:54:10 UTC

[Tapestry Wiki] Update of "Tapestry5How to make a basic crud" by michaelcourcy

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for change notification.

The following page has been changed by michaelcourcy:
http://wiki.apache.org/tapestry/Tapestry5How_to_make_a_basic_crud

New page:
=== Basic CRUD with Tapestry 5 ===

==== Introduction ==== 

This tutorials aims to present you how easy and elegant could be the conception of a Crud cycle in tapestry 5.

In order to stay focused on the question of CRUD we're not going to deal with a database or wondering about transactions. If you want to work on a tutorial that deals with this question in great details you should [http://wiki.apache.org/tapestry/Tapstry5First_project_with_Tapestry5,_Spring_and_Hibernate read this one carrefully].

==== Create the project =====

To create the project and setting up all the dependencies we use maven :

{{{

mvn archetype:create  
   -DarchetypeGroupId=org.apache.tapestry 
   -DarchetypeArtifactId=quickstart 
   -DarchetypeVersion=5.0.5 
   -DgroupId=org.apache.tapestry  
   -DartifactId=basicCrud 
   -DpackageName=org.apache.tapestry.tutorial.basiccrud 

}}}

Now let's move in the project and and make it available in eclipse
{{{
 cd basicCrud
 mvn eclipse:eclipse
}}}

Import the project in eclipse : File -> Import -> General -> Existing Project Into Workspace 
Browse to the folder basicCrud and click finish.

we are ready to work.

==== Create the model ==== 

Create in the package org.apache.tapestry.tutorial.basiccrud.model our model class, as you can see I made it simple : 

{{{

package org.apache.tapestry.tutorial.basiccrud.model;

public class MyBean {
	
	
	private Long id;
	private String name;

	public MyBean(){
		//nothing to do 
	}
	
	public MyBean(String name){
		this.name = name;
	}
	
	public MyBean(String name, Long id){
		this.name = name;
		this.id = id;
	}
	
	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return id + " : " + name;
	}


}

}}}

 * The id is going to identify a bean 
 * The name is just a property for the only purpose of this tutorial

==== Create the Service ==== 

In this tutorial as explained at the beginning we just target the crud process, thus we're going to make a very simple BeanManager that hold a list of MyBean in memory, this service is going to be injected (more on this later) as a Singleon. Thus, as long a your application is deployed the list is still in memory, but every time you restart the server the list is reinitialized. There's no persistence between server reboot.

To make a service we need an interface and an implementation. If you wonder why we could not only work with an implementation, you should read [http://tapestry.formos.com/nightly/tapestry5/tapestry-ioc/overview.html this].

In org.apache.tapestry.tutorial.basiccrud.services.manager create the interface BeanManager
{{{

package org.apache.tapestry.tutorial.basiccrud.services.manager;

import java.util.List;

import org.apache.tapestry.tutorial.basiccrud.model.MyBean;

public interface BeanManager {

	public abstract List<MyBean> getMyBeans();

	public abstract void setMyBeans(List<MyBean> myBeans);
	
	public void delete(Long id);
	
	public abstract void save(MyBean myBean);
	
	public MyBean getMyBean(Long id);	

}


}}}

In the same package make the implementation 
{{{

package org.apache.tapestry.tutorial.basiccrud.services.manager;

import java.util.ArrayList;
import java.util.List;

import org.apache.tapestry.tutorial.basiccrud.model.MyBean;

public class BeanManagerImpl implements BeanManager {
	
	private List<MyBean> myBeans = new ArrayList<MyBean>();

	/** 
	 * 
	 * @see org.apache.tapestry.tutorial.basiccrud.services.manager.impl.BeanManager#getMyBeans()
	 */
	public List<MyBean> getMyBeans() {		
		return myBeans;  
	}

	/**
	 * 
	 * @see org.apache.tapestry.tutorial.basiccrud.services.manager.impl.BeanManager#setMyBeans(java.util.List)
	 */
	public void setMyBeans(List<MyBean> myBeans) {
		this.myBeans = myBeans;
	}
	
	/**
	 * 
	 * @see org.apache.tapestry.tutorial.basiccrud.services.manager.impl.BeanManager#delete(org.apache.tapestry.tutorial.basiccrud.model.MyBean)
	 */
	public void delete(Long id){
		MyBean myBean = getMyBean(id);
		getMyBeans().remove(myBean);
	}
	
	/**
	 * 
	 * @see org.apache.tapestry.tutorial.basiccrud.services.manager.impl.BeanManager#save(org.apache.tapestry.tutorial.basiccrud.model.MyBean)
	 */
	public void save(MyBean myBean){
		if(myBean.getId()!=null){
			//update
			int i=0;
			for (MyBean iteration : myBeans){
				i++;
				if (iteration.equals(myBean)){
					break;
				}
			}		
			myBeans.set(i-1, myBean);
		}else{
			myBean.setId(new Long(myBeans.size()));
			myBeans.add(myBean);
		}
	}
	
	public MyBean getMyBean(Long id){
		for(MyBean myBean : myBeans){
			if (myBean.getId().equals(id)){
				return myBean;
			}
		}
		return null;
	}
	
	@Override
	public String toString() {
		return myBeans.toString();
	}
	
	

}


}}}


==== Inject the service ====

Injecting a service in Tapestry is really easy, just add a bind method to your AppModule.java 
in org.apache.tapestry.tutorial.basiccrud.services.AppModule.java add this method
{{{

public static void bind(ServiceBinder binder)
{
     
      binder.bind(BeanManager.class, BeanManagerImpl.class);
      
}
	
}}}

Now the BeanManager is available in any tapestry component through the @Inject annotation.

==== Display a list of beans in the Start page ====

Change the Start.java to display a list of beans, and handles some Crud action 
{{{

package org.apache.tapestry.tutorial.basiccrud.pages;

import java.util.List;

import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.InjectPage;
import org.apache.tapestry.tutorial.basiccrud.model.MyBean;
import org.apache.tapestry.tutorial.basiccrud.services.manager.BeanManager;

/**
 * Start page of application basicCrud.
 */
public class Start{	
	
	@Inject	
	private BeanManager beanManager;
	
	@InjectPage
	private Save save;
	
	private boolean emptyList;
	
	private MyBean myBean;
	
	public MyBean getMyBean() {
		return myBean;
	}

	public void setMyBean(MyBean myBean) {
		this.myBean = myBean;
	}

	public List<MyBean> getMyBeans(){
		return beanManager.getMyBeans();
	}

	public boolean isEmptyList() {
		return beanManager.getMyBeans().isEmpty();
	}
	
	public Object onActionFromCreate(){
		MyBean myBean = new MyBean();
		myBean.setName("Choose a name");		
		save.setMyBean(myBean);
		return save;
	}
	
	public Object onActionFromEdit(Long id){
		save.setMyBean(beanManager.getMyBean(id));
		return save;
	}
	
	public void onActionFromDelete(Long id){
		beanManager.delete(id);
	}
	
	
}

}}}

Notice that: 

 * We inject the beanManager service through the @Inject annotation
 * onActionFromCreate that initialize a new bean, pass it to the save page and return the Save page, the Save page is going to hold the form.
 * onActionFromEdit, that retreives a bean with its id, pass it to the save page and return the Save page.
 * onActionFromDelete that just remove the bean from the list but return nothing, because we stay on the same page. The list is only refreshed.

 Change Start.html in the WEB-INF directory
 {{{
 
 <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <head>
        <title>basicCrud Start Page</title>
    </head>
    <body>
        <h1>basicCrud of MyBean</h1>
		
		<p><t:actionlink t:id="create">Create a new MyBean</t:actionlink></p>
		
		<t:if test="emptyList">
		
			<p>There's no MyBeans in the list</p>
		
			<t:parameter name="else">
				<t:loop source="myBeans" value="myBean">
				  ${myBean.name}
			      <t:actionlink t:id="edit" context="myBean.id">Edit</t:actionlink>
			      <t:actionlink t:id="delete" context="myBean.id">Delete</t:actionlink>
			      <br/>
			    </t:loop>	
		    </t:parameter>
				
			
		</t:if>		

        
    </body>
</html>
 
 }}}
 
 For each id 
 {{{
 
 <t:actionlink t:id="edit" context="myBean.id">Edit</t:actionlink>
 
 }}}
 
 We made the corresponding handler
 
 {{{
 
 public Object onActionFromEdit(Long id){
		save.setMyBean(beanManager.getMyBean(id));
		return save;
}
 
 }}}
 
 
 ==== Edit or create a bean ====
 
To create or edit a bean we'll use Save.java :
{{{
 
package org.apache.tapestry.tutorial.basiccrud.pages;

import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.InjectPage;
import org.apache.tapestry.annotations.Persist;
import org.apache.tapestry.tutorial.basiccrud.model.MyBean;
import org.apache.tapestry.tutorial.basiccrud.services.manager.BeanManager;

public class Save {
	
	@Persist	
	private MyBean myBean;
	
	@Inject
	private BeanManager beanManager;

	@InjectPage
	private Start start;
	
		
	public MyBean getMyBean() {
		return myBean;
	}

	public void setMyBean(MyBean myBean) {
		this.myBean = myBean;
	}	
	
		
	public Object onSubmit(){		
		beanManager.save(myBean);
		return start;
	}

}
 
}}}

Which is quite self explainatory.

And Save.html 
{{{

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
<title>basicCrud edit Page</title>
</head>
<body>

   
    ${myBean.name}<br/>
    ${myBean.id}<br/>
   
	<t:form>
      <t:errors/>
      <t:label t:for="name"/> 
	  <input t:type="textfield" t:id="name" t:value="myBean.name"/><br/>
      <br/>
      <input type="submit"/>
    </t:form>



</body>
</html>

}}}


==== Try it ====
now try it : 

{{{
mvn clean compile jetty:run 
}}}

And just navigate to http://localhost:8080 you'll find your way ;-).

==== Conclusion ==== 

As you can see building a CRUD cycle in Tapestry 5 is really easy. Instead of the other framework we didn't use a code generator or other magic un/ex-plicit rules, things are clear from the start and you know exactly what you do. 

Even in this example tutorial we where able to separate the service layer from the mvc layer without wrinting a single line of xml.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org