views:

239

answers:

2

Hello all, I am trying to deploy a simple spring app. It takes a username(from a jsp), insets the value into a db and displays a greeting on a new jsp page saying hello!, [username].

My environment is:

  • OS: windows xp professional
  • Db: MS access (this is just for trying things out at first, intend to shift to mySQL)
  • IDE: eclipse
  • Server: Tomcat 6

I get an error as below:

Feb 25, 2010 11:21:04 AM org.springframework.web.servlet.FrameworkServlet processRequest SEVERE: Could not complete request java.lang.IllegalArgumentException: dataSource is required
      at org.springframework.jdbc.support.JdbcAccessor.afterPropertiesSe(JdbcAccessor.java:130)
      at org.springframework.jdbc.core.JdbcTemplate.<init>(JdbcTemplate.java:122)
      at SpringClasses.Profile.setUsername(Profile.java:32) ………

The applicationContext file is as below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd"&gt;
<beans>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
    <property name="dataSource"><ref bean="dataSource"/></property> 
</bean> 

<bean id="Profile" class="SpringClasses.Profile"> 
    <property name="dataSource"><ref bean="dataSource"/></property> 
</bean>

<bean id="dataSource"       class="org.springframework.jdbc.datasource.DriverManagerDataSource" singleton="true" destroy-method="close">
    <property name="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver"/>
    <property name="url" value="jdbc:odbc:usernamedb"/>
    <property name="username" value="admin"/>
    <property name="password" value=""/>
</bean>
</beans>
</code>

I have set the DSN (usernamedb) under control panel ->admin tools->odbc sources->user DSN.The problem seems to be with the URL of the dataSource.

The relevant java code from the controller class and bean class are as below

From the ProfileFormController.java class:

protected ModelAndView onSubmit(Object command)
{
  Profile profile = (Profile) command; 
  String greeting = "Hello," + profile.getUsername() + "!";
  profile.setUsername(profile.getUsername());
  return new ModelAndView("greetingDisplay", "greeting", greeting);
}

From the Profile.java class:

private String username;
private JdbcTemplate jt;
private DataSource dataSource;

public Profile() {
 }

public Profile(String username) {
this.username = username;
}

public String getUsername() {
return username;
}
public String setUsername(String username) {
int rowsInserted;
setDataSource(dataSource);
jt = new JdbcTemplate(dataSource);
rowsInserted = jt.update("insert into username_db (username) values(?)",new Object[]      {username});

//System.out.println("In Profile.getUsername, num. of rows inserted:"+rowsInserted);
return username;
 }
public void setDataSource(DataSource dataSource) {
 this.jt = new JdbcTemplate(dataSource);
  }

Configured the Profile bean in web.xml as below:

<bean id="profileFormController" class="SpringClasses.ProfileFormController">
    <property name="commandName">
       <value>profile</value
    </property>
    <property name="formView">
       <value>profile</value>
    </property>
    <property name="successView">
       <value>greetingDisplay</value>
    </property>

 </bean>

Within ProfileFormController, I'm setting the constructor as below:

public ProfileFormController() { 
  setCommandClass(Profile.class); 
  setCommandName("profile"); }

Added the contextLoaderServlet in web.xml too.

What am I missing? Help is much appreciated.

Thanks
Neetu.

+1  A: 

If you creating Profile command inside method formBackingObject then it will haven't processed by Spring, and not populated with a dataSource. You can set it at this method, or get bean from spring beans holder.

Also you need to know that when you creating spring bean it's singleton, by default. It means that all your controllers will use (and modify) one instance of this. Imho it's not what you want. You can use scope="request" for your model beans.

Or it's better to stay model clean, as simple POJO, and move all db centric code into controller / db layer.

splix
A: 

You are trying to apply DDD (domain driven design) with spring, which is not easy. The "gap" is because:

  • domain objects have to be instantiated by you
  • domain objects should be spring-managed, in order to apply dependency injection.

Read this for some hints about implementing DDD with spring.

Or if you are not sure whether you want to use DDD, then follow splix's advice and separate the data from the business operations.

(DDD means that your classes define both the data and the operations on that data. In non-DDD they are separated. You are getting the exception because (perhaps) the Profile is instantiated by you, rather than by the spring framework)

Bozho
Following splix's advice, I have created a ProfileDao class with the database related operation. I still fail to to understand why I'm getting the "dataSource required exception". Also, I'm a spring newbie and the whole DDD part went over my head. Do I need to add/delete some configuration? Change the URL maybe?
Pratyusha
no. DDD means that your objects contain both data and the operations on that data. In non-DDD they are separated. You are getting the exception because (perhaps) the Profile is instantiated by you, rather than by the spring framework.
Bozho