tapestry : activation context

Posted in java, tapestry5, web framework with tags , , , , , on 18 listopada, 2009 by eyemirror

when switching from one page to another usually we want to pass some data to the next page. We can persist data in session or append them to the url.

Tapestry handles both cases. Putting values to the session is easy and discussed here (persistent page data and persistent state).

Tapestry comes with an idea of activation context that is a way to pass values to itself or to another page. Usually activation context is related to PageLink or ActionLink components but not only and is way to confusing at the beginning. So let see how we can play with it.

Say we have two pages – Index and Address and that from Index page we can choose address and then see it in the Address page.

//Index.tml
<p>${message:addressgrid-label}</p>
<t:grid source="addresses" row="address" model="addressesModel"
        reorder="city, name"
        add="action">
    <p:nameCell>
        ${address.name} ${address.surname}
    </p:nameCell>
    <p:actionCell>
        <t:pagelink t:page="address" t:context="address.id">select</t:pagelink>
    </p:actionCell>
    <p:empty>
      <p>no data.</p>
    </p:empty>
</t:grid>

//Address.java
//the event triggered is assigned with Address onActivate action
...
void onActivate(Long id){
    this.id = id;
}

and each link created will be formated like http://myhost/myapp/address/NN where NN is a id from selected entity. but that s easy. The same we can do when using the actionlink component and use the value in event handle.

Now it comes the trickier part. What if we want to pass more then one value in url. Tapestry allows us to call a getter that will return array or collection of Objects.

//Index.java
...
@Property
private Address address;

public String [] getSelectedContext(){
    return new String[] {address.getName(), this.otherClassFieldToPass};
}
//and in Index.tml
<p:actionCell>
    <t:pagelink t:page="address" t:context="selectedContext">select</t:pagelink>
</p:actionCell>

The problem I got was that you can add another argument to onActive callback or if you are not sure how many arguments you will pass then it should be possible to use varargs – well it should but it just doesn’t work. So there is another way and EventContext class becomes very handy.

void onActivate(EventContext context){
    Logger l = Logger.getLogger(this.getClass());
    l.debug("args "+context.toString());
    l.debug("args 1"+context.get(String.class, 0));
    l.debug("args 0"+context.get(String.class, 0));
}

Activation context can be set by t:context param in components or by onPasivate() that returns Object and that will be used to activate the page with default values if t:context is omitted in Page or Action Link

tapestry extending start example

Posted in hibernate, java, java ee, jpa, spring, spring framework, tapestry5, web framework with tags , , , , , , , on 5 listopada, 2009 by eyemirror

lets examine starting tutorial from tapestry

creating project

http://tapestry.apache.org/tapestry5/tutorial1/first.html

mvn archetype:create
-DarchetypeGroupId=org.apache.tapestry
-DarchetypeArtifactId=quickstart
-DgroupId=org.apache.tapestry
-DartifactId=tutorial1
-DpackageName=org.apache.tapestry5.tutorial

when I typed command my maven shell printed nice error message saying that something went wrong and it gives up. but the command below will work and will create all nice preconfigured project for us

mvn archetype:generate
-DarchetypeCatalog=http:/</tapestry.formos.com/maven-snapshot-repository
-DarchetypeGroupId=org.apache.tapestry
-DarchetypeArtifactId=quickstart
-DgroupId=my.package
-DartifactId=mywebapp

the other way round would be creating simple maven web project and then editing pom file to get all necessary libraries.

If you want pretty printing for framework exception messages add

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.0.2</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
                <optimize>true</optimize>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>maven-jetty-plugin</artifactId>
            <version>6.1.9</version>
            <configuration>
                <!-- Log to the console. -->
                <requestLog implementation="org.mortbay.jetty.NCSARequestLog">
                    <!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
                         that prevents the requestLog from being set. -->
                    <append>true</append>
                </requestLog>
            </configuration>
        </plugin>
    </plugins>
  ...
</build>
<strong><reporting>
    <!-- Adds a report detailing the components, mixins and base classes defined by this module. -->
    <plugins>
        <plugin>
            <groupId>org.apache.tapestry</groupId>
            <artifactId>tapestry-component-report</artifactId>
            <version>${tapestry-release-version}</version>
            <configuration>
                <rootPackage>info.kamiseq</rootPackage>
            </configuration>
        </plugin>
    </plugins>
</reporting></strong>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

tapestry and hibernate

http://tapestry.apache.org/tapestry5/tutorial1/forms2.html
I couldn’t force my project to work with db through hibernate. I had huge problems with tapestry-hibernate lib. so I switched to spring and configured hibernate as a JPA’s vendor. Anyway you don’t need that either, to finish the tutorial just create simple dao object that will hold HashMap of Address object to hold created with site addresses.

tapestry and IOC

tapestry works with Inversion of Control framework of its own. So there is no need to use external framework like spring inject you custom objects in simple app. to configure IOC you need create (unless there is one) AppModule in your.package.services package and add

public static void bind(ServiceBinder binder){
    binder.bind(AddressDAO.class, AddressRdmsDao.class);
}

then you can use @Inject with your interface like any other service (bean)

@Injectprivate AddressDAO dao;

extending the tutorial’s example

I added row parameter to the grid (in Index.tml) so I could add action links and customizing grid’s content but then I wished to had action link that will show item in the grid in t:beandisplay component. ok let’s go..

in Index.java

@Property
@Persist
private Address address;
@Inject
private BeanModelSource beanModelSource;
@Injectprivate ComponentResources resources;
//this will control grid's display model but it can be done with add/reorder/include paramateres in the tml
public BeanModel<Address> getAddressModel() {
    BeanModel<Address> model = beanModelSource.createDisplayModel(Address.class, resources.getMessages());
    model.add("action", null);
    return model;
}
//to handle show action
Object onActionFromShow(Long id) {
    this.address = this.dao.find(id);
    return this;
}

in Index.tml

<t:grid source="addresses" row="address" model="addressModel"
    reorder="honorific, firstName, lastName, email, phone, street1, street2, city, zip, country, action"
    add="show">
    <t:parameter name="actionCell">
        <t:pagelink page="address/create" t:context="address.id">update</t:pagelink>
    </t:parameter>
    <t:parameter name="showCell">
        <t:actionLink t:id="show" t:context="address.id">show</t:actionLink>
    </t:parameter>
    <p:empty>
        <p>Brak danych, wprowadź addresata - <t:pagelink page="address/create">dodaj</t:pagelink>.</p>
    </p:empty>
</t:grid>
<ul>
    <li><t:pagelink page="address/create">Create new address</t:pagelink></li>
</ul>

ok so we have show action that will set address reference to wanted object. but if we put t:beandisplay component below t:grid then we will see the last object processed by grid (as the grid and beandisplay uses the same property address). So to see the address we clicked on then wee need to use different name for property or swap grid and display components places, is there any other way??????.

<t:if test="address">
    <t:beandisplay object="address">
    </t:beandisplay>
</t:if>
<t:grid source="addresses" row="address" model="addressModel"
        reorder="honorific, firstName, lastName, email, phone, street1, street2, city, zip, country, action"
        add="show">
    <t:parameter name="actionCell">
        <t:pagelink page="address/create" t:context="address.id">update</t:pagelink>
    </t:parameter>
    <t:parameter name="showCell">
        <t:actionLink t:id="show" t:context="address.id">show</t:actionLink>
    </t:parameter>
    <p:empty>
      <p>Brak danych, wprowadź addresata - <t:pagelink page="address/create">dodaj</t:pagelink>.</p>
    </p:empty>
</t:grid>
<ul>
    <li><t:pagelink page="address/create">Create new address</t:pagelink></li>
</ul>

and finally surround t:beandisplay with t:if to test existance of address object

limitations of Hibernate

Posted in hibernate, java, java ee, Java Persistence API, jpa, remoting with tags , , , , , , , , , , , on 19 stycznia, 2008 by eyemirror

Serialization issue

I have found that my Hibernate’s entities are working fine only when I am using them locally by jsp-es or servlets.

Unfortunately my goal was to connect thick client to server. That time I was using flex 3 to build client and AMF3 protocol with weborb to invoke remote methods on my Spring’s beans. The problem I run into was that I used lazy initialization in entities and while serializing LazyInitializationException is thrown. It is natural as serialized object is detached from session (context) and something (serialization process) is getting data from entity.

It seems that it can be solved,

  1. by using OSIV filter(open session in view) – but really I don’t know if serialization will not fetch lazy initialized collections.
  2. by using custom object-queries to return a simple object or collection of objects rather than entity (look to JPA specification).
  3. by mapping entities with Dozer framework – in my opinion, it is not really promising for more complicated entities relationships with lazy, eager combinations.

I don’t have too much time now, so check it by yourself.

Fortunately for me I switch to java desktop application and there I can use spring’s HttpInvoker.

Extending entity issue

When creating hierarchy of entities that are stored in the same DB table, you need to be careful with relationships between them. I don’t know why, but Hibernate is not always using @DiscriminatorColumn flag to filter data set and that is violating Collection type.

Take care.

extended example

Posted in entities mapping, entity, hibernate, java ee, Java Persistence API, jpa, mapping with tags , , , , , , on 19 stycznia, 2008 by eyemirror

The good news is, finally I mapped my model using Hibernate’s entities that perfectly fits to my DB model. Only this time I started with creating db tables and then force Hibernate to persist data to right table in right way.

On the other hand I am not so sure if people are doing things this way. I should rather think in terms of object and relationships they have and don’t care about backstage operations (that is hard if you know sql a bit). Well I really don’t have much experience about ORM’s performance in big scale, but as objects are cached and people use that I think it provides good trade-off between simplicity and speed. And it is perfect to start project and then optimize specific queries in native SQL dialect/adding cache and so on – using plain SQL will not guarantee any speed-up.

UML diagrams
uml model

Entities

  1. here is the zip file with chosen entities from my project (not all of them). To unzip the file use the password ‚djshadow‚ :) hell yeah (I am using 7zip softwear)
  2. customer entity is a base class for all concern, owner, service and integrator classes. each concern can be owner as well and each integrator can be service. There is a ManyToMany relationship between service and station split into 2 OneToMany relationships that is holding additional filed for that relationship

//TODO
get reed of relationship annotations and move them to xml file where they can be changed easily without recompiling classes.

mapping objects

Posted in java, java ee, Java Persistence API, jpa on 23 grudnia, 2007 by eyemirror

ok lets discuss how object can be persist and retrieve
at least two things need to be taken under account writing your entities

  1. direction in relationships – take a look. And a good example showing relations between objects http://java.boot.by/scbcd5-guide/ch05s04.html. Notice how each relation is mapped to DB.And something interesting about hibernate, thing I was so confused about. (I’ve took it form one of polish google group so If you are interested in whole post go to http://groups.google.com/group/pl.comp.lang.java/brows)
    „Transparent POJO-oriented persistence implementations such as Hibernate do not implement managed associations. Contrary to CMR, Hibernate associations are all inherently unidirectional.”

    following the author, Hibernate is not too clever and can’t figure out that objects are related in both way, we should assign them manualy, and he is advising simple code like this

    @Entity
    class Company {
    ...
            public void addEmployee(Employee empl) {
                    getEmployees().add(empl);
                    empl.setCompany(this);
    
            }
    }
  2. fetching style – lazy or eager – defined in your
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)

    annotation. Main difference is when collection of your related entity is created. One important thing to remember is that each fetch operation is within transaction. After that transaction success and your fetch type is lazy, you can’t get collection of related objects. One solution is to fetch with eager type but this makes a lot of sql selects to your DB and you use more memory for your objects. It doesn’t matter for 1000 records in your DB but over 10000 it can make a difference.

    As far as I’m concerned better way is to lazy fetch and then use em.merge(object) method on object that is currently outside transaction. the method will set all related collection.

simple entity mapping example

Posted in entities mapping, entity, java, java ee, Java Persistence API, jpa, mapping on 23 grudnia, 2007 by eyemirror

because Entities are just simple POJOs there is nothing really to talk about.
The good idea is to implement from Serializable interface and override int hashCode(), boolean equals(Object object) and String toString() methods. With IDE like netbeans it is all auto generated for you so you don’t need to worry about.

package pl.mypck.db;

import ...;

@Entity
@NamedQueries({
    @NamedQuery(name = "Book.fetchAuthor", query = "SELECT b FROM Book b WHERE b.author = :author"),
    @NamedQuery(name = "Book.fetchAllBooks", query = "SELECT b FROM Book b")
})
public class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    private String author;
    private List<Page> pages = new ArrayList();

    public void setId(Long id){this.id = id;}
    public void setAuthor(String a){this.author = a;}
    public void setPages(List<Page> ps){this.pages = ps;}

    public void addPages(Page p){
        this.pages.add(p);
    }

    @Id
    @SequenceGenerator(name="BOOK_SEQ", allocationSize=0, sequenceName="BOOK_SEQ")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="BOOK_SEQ")
    @Column(name="id_book")
    public Long getId() {
        return id;
    }
    public String getAuthor(){return this.author;}
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    // when bidirectional mapping
    //with bidirectional mapping one should add mappedBy="book" to @OneToMany annotation
    public List<Page> getPages(){
        return this.pages;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Book)) {
            return false;
        }
        Book other = (Book) object;
        if ((this.id == null &amp;&amp; other.id != null) || (this.id != null &amp;&amp; !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return " pl.mypck.db.Book[id=" + id + "]";
    }
}
//Page class
package pl.mypck.db;

import ...;

@Entity
public class Page implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //private Book book; // when bidirectional mapping
    private String content;

    public void setId(Long id){this.id = id;}
    //public void setBook(Book b){this.book = b;}/* when bidirectional mapping */
    public void setContent(String c){this.content = c;}

    @Id
    @SequenceGenerator(name="PAGE_SEQ", allocationSize=0, sequenceName="PAGE_SEQ")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PAGE_SEQ")
    public Long getId() {return id;}
    //@ManyToOne(cascade={CascadeType.ALL})/* when bidirectional mapping */
    //@JoinColumn(name="id_book")/* when bidirectional mapping */
    //public Tabela getBook() {return this.book;}/* when bidirectional mapping */
    public String getContent(){return this.content;}

    /*
     *
     */
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Page)) {
            return false;
        }
        Page other = (Page) object;
        if ((this.id == null &amp;&amp; other.id != null) || (this.id != null &amp;&amp; !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "pl.mypck.db.Page[id=" + id + "]";
    }
}

A book object has its pages and here only Book knows about its pages (aka indirect mapping).

Page p = new Page();
p.setContent("text on first page");
Book b = new Book();
b.addPages(p);

very simple very nice, I like it:)
it is working, fetching and inserting or updating, deleting but what Hibernate created in DB system sometimes scares me out.

about Jpa (Java Persistence API)

Posted in hibernate, java, java ee, Java Persistence API, jpa on 23 grudnia, 2007 by eyemirror

a good starting point

the good thing about using JPA is that we can work with different vendors like Hibernate or TopLink underneath, without focusing on specific implementation. In another words we have next layer of abstraction of accessing data.

Main benefits of using JPA are:

  • thinking in terms of objects
  • quick implementation of data model
  • no need to care about DB tables implementation
  • for simple mappings you have everything ready to work
  • no need to implement mappers to and from object to your db

Disadvantages are:

  • SQL queries are not that optimized (like everything that is for general use). So if you need something fast think about using something different.
  • frameworks (like Hibernate) are not that intelligent as you could expect.
  • when your model gets complex, you need to write queries anyway to retrieve objects

Of course there are some possibilities to overcome problems I’ve mention above.
Good enough to start, check related topics.

configuring Tomcat and spring framework

Posted in java, java ee, spring, spring framework, Tomcat on 23 grudnia, 2007 by eyemirror

add this to your web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/springConfig.xml</param-value>
    </context-param>
    <listener>
        <description>domyslny listener dla sF</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
..
..
</web-app>

ok and now prepare your spring xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/dbname"/>
        <property name="password" value="pass"/>
        <property name="username" value="user"/>
        <property name="poolPreparedStatements"><value>true</value></property>
        <property name="maxActive"><value>10</value></property>
        <property name="maxIdle"><value>10</value></property>
    </bean>
    <bean id="injectionTest" class="pl.mypck.InjectionTest">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

read more in spring documentation about IoC and beans http://static.springframework.org/spring/docs/2.5

where to start

Posted in java, java ee on 22 grudnia, 2007 by eyemirror

good to read

download first

  • http://www.springframework.org/
  • http://tomcat.apache.org/ – if you want to use tomcat with some IDE like netbeans or eclipse, download zip package instead of win-installer as it doesn’t have start-up and stopping file with it. win installer is using services to start and stop server.
  • http://www.netbeans.org/ – ready to use. 6th version is OK. I had impression that it has problems with deploying my war files on server.
  • http://www.eclipse.org/downloads/ – heh for inexperienced user as I am it was and sometimes it is a nightmare to configure it. or maybe I had just a bad luck.

purpose

Posted in Uncategorized on 22 grudnia, 2007 by eyemirror

recently I ve started my adventure in enterprise solutions from sun. still I have a lot to learn but I want to have a place where I could put some examples how I solve problems.

I hope my blog will help someone trying familiarize with j2ee, the way you have helped me.