JdbcDaoSupport
, Spring's nice and handy JDBC tool.I prefer not to deal with automatic configurations generated by Wicket or Spring IDE plugins, but to create the application from scratch. I will be using the NetBeans IDE. In a nutshell, all we'll have to do, is download some libraries, put some of them in Tomcat's
lib
folder, the rest in the classpath, and make a couple of modifications to web.xml
and applicationContext.xml
files.Libraries
First of all, you will need Wicket and Spring libraries. If you download Spring with all dependencies, most probably, you won't have to download anything else (except
mysql-connector
, if you don't already have it).Specific jars are:
—
aspectjrt-1.x.jar
—
cglib-nodep-2.x.jar
—
log4j-1.x.jar
—
slf4j-api-1.x.jar
—
slf4j-log4j12-1.x.jar
—
spring-2.x.jar
—
wicket-1.3.x.jar
—
wicket-ioc-1.3.x.jar
—
wicket-spring-1.3.x.jar
—
wicket-spring-annot-1.3.x.jar
Those jars listed above you should add to the libraries of your NetBeans project.
These three you have to put in
$CATALINA_HOME/lib
folder. Don't put them in classpath unless you've got several hours to find out why doesn't anything work.—
commons-logging-1.1.x.jar
—
ehcache-1.2.x.jar
—
mysql-connector-java-5.1.x-bin.jar
context.xml
Hope you've already created a NetBeans project and selected a “Web Application” at certain point.
First thing to do, is describe a database resource so we could access it via JNDI. To do this, put in the
META-INF/context.xml
something like this:<?xml version="1.0" encoding="UTF-8"?>
<Context path="/Chicago">
<!-- database resource -->
<Resource
name="jdbc/Chicago"
auth="Container"
driverClassName="com.mysql.jdbc.Driver"
type="javax.sql.DataSource"
username="database_user"
password="database_pass"
url="jdbc:mysql://localhost/my_database"
maxWait="10000"
maxActive="60"
minIdle = "0"
maxIdle="30"
removeAbandoned="true"
removeAbandonedTimeout="120"
testOnBorrow="false"
testOnReturn="false"
testWhileIdle="true"
validationQuery="SELECT 1"
timeBetweenEvictionRunsMillis="59000"
minEvictableIdleTimeMillis="58000"
/>
</Context>
Such resource configuration will tell your servlet container (namely, Tomcat) to keep alive JDBC connections and reconnect to avoid IO exceptions when connection isn't being used for a long time.
applicationContext.xml
You will now have to create a
WEB-INF/applicationContext.xml
file for Spring configuration.Here's what you might want to put there:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/Chicago"/>
</bean>
<!-- Wicket WebApplication setup -->
<bean id="wicketApplication" class="com.mycorp.chicago.ChicagoApplication">
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDaoTarget" class="com.mycorp.chicago.user.JdbcUserDao">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="proxyTargetClass" value="true"/>
<property name="target" ref="userDaoTarget" />
<property name="transactionAttributes">
<props>
<prop key="save">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="*">PROPAGATION_REQUIRED,-Exception,readOnly</prop>
</props>
</property>
</bean>
</beans>
What we just did there,
a) configured a
dataSource
object which is used in JdbcDaoSupport
, to lookup database resource via JNDI;b) told Spring to use Acegi filter on HTTP requests (Acegi is Spring's security framework, we'll deal with it in the next episode);
c) created a proxy DAO bean.
web.xml
We now must ask container to invoke Spring filter on certain requests. This is what we do in
WEB-INF/web.xml
.<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Lianet Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>Spring Application Factory Filter</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationFactoryClassName</param-name>
<param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Spring Application Factory Filter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
</web-app>
UserDao.java and JdbcUserDao.java
For Spring injection to work, we create an interface of the DAO and its JDBC implementation. These I will keep in
com.mycorp.chicago.user
package./*
* UserDao.java
*/
package com.mycorp.chicago.user;
import java.io.Serializable;
/**
*
*/
public interface UserDao extends Serializable /* UserDetailsService */ {
public void test();
}
/*
* JdbcUserDao.java
*/
package com.mycorp.chicago.user;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
*
*/
public class JdbcUserDao extends JdbcDaoSupport implements UserDao {
public void test() {
getJdbcTemplate().query("SELECT name FROM my_table WHERE id=1", new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
String name = rs.getString("name");
System.out.println("Got object name: " + name);
return null;
}
});
}
}
You probably have already got the idea that to have all the preceding work, you'll need a MySQL database “my_database” with a “my_table” table with the latter consisting of at least an integer `id` and a
varchar
`name` fields.IndexPage.java
Now let's inject our brand new
UserDao
in some Wicket component. Say, an index page of the app. I'll put it in the com.mycorp.chicago.web.page
package./*
* Index.java
*/
package com.mycorp.chicago.web.page;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.spring.injection.annot.SpringBean;
import com.mycorp.chicago.user.UserDao;
/**
* Main page of the application.
*/
public class IndexPage extends WebPage {
@SpringBean(name="userDao")
private UserDao userDao;
public IndexPage() {
add(new Label("sampleLabel", "This is a text which is also a model."));
userDao.test();
}
}
IndexPage.html
By default, HTML template is stored along with the java source.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<span wicket:id="sampleLabel">Sample label</span>
</body>
</html>
ChicagoApplication.java
Now all that is left is the actual
WebApplication
of Wicket./*
* ChicagoApplication.java
*/
package com.mycorp.chicago;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import com.mycorp.chicago.web.page.IndexPage;
/**
*
*/
public class ChicagoApplication extends WebApplication {
@Override
public Class getHomePage() {
return IndexPage.class;
}
@Override
public void init() {
super.init();
addComponentInstantiationListener(new SpringComponentInjector(this));
}
}
Enjoy
That's it. Now all that is left is to hit F6 button and wait for results. If you get a
ClassNotFound
exception, you probably forgot to add certain library. Wicket runtime exceptions are usually easy to fix since Wicket is very verbose in development mode.
1 comment:
When I execute the following configuration I am getting the following exception. Kindly let me how to handle this.
org.apache.wicket.WicketRuntimeException: Can't instantiate page using constructor 'public com.wicket.pages.IndexPage()'. Might be it doesn't exist, may be it is not visible (public).
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:196)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:68)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:101)
at org.apache.wicket.session.DefaultPageFactory.newPage(DefaultPageFactory.java:47)
at
..............
Post a Comment