Announcement Announcement Module
Collapse
No announcement yet.
Why i am getting ClassNotFoundException DuplicateKeyException Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why i am getting ClassNotFoundException DuplicateKeyException

    Here is what i did..

    1. created 3 xml files. db-context.xml, env-context.xml, infrastructure-context.xml
    2. created 1 xml file webapp-config.xml ( it imports the beans from above 3 files and later set in contextParam)
    3. created a properties file containing db details

    there contents are as follows
    Code:
    db-context.xml
    <bean id="dataSource"
    		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="${db.driver}"></property>
    		<property name="url" value="${db.url}"></property>
    		<property name="username" value="${db.username}"></property>
    		<property name="password" value="${db.password}"></property>
    	</bean>
    
    	<bean id="transactionManager"
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource"></property>
    	</bean>
    Code:
    env-context.xml
    <bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    	<property name="locations">
    		<list>
    			<value>classpath:/bootstrap/db-mysql.properties</value>
    		</list>
    	</property>
    </bean>
    Code:
    infrastructure-context.xml
    <batch:job-repository id="jobRepository" data-source="dataSource" transaction-manager="transactionManager" isolation-level-for-create="SERIALIZABLE" />
    
    <bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    	<property name="jobRepository" ref="jobRepository"></property>
    	<property name="taskExecutor" ref="jobLauncherTaskExecutor"></property>
    </bean>
    <task:executor id="jobLauncherTaskExecutor" pool-size="20"/>
    Code:
    db-mysql.properties
    db.driver=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://10.2.10.15/:3306/jobrepository
    db.username=dev
    db.password=password
    Code:
    webapp-config.xml
    
    <import resource="classpath*:/bootstrap/*.xml"/>
    Code:
    HomeController.java
    @RequestMapping(value = "/",method = RequestMethod.GET)
    	public String home(Locale locale, Model model) {
    		ApplicationContext ctx=new ClassPathXmlApplicationContext("/webapp-config.xml");
    		Job job=new SimpleJob("myjob1");
    		JobLauncher launcher=ctx.getBean(JobLauncher.class);
    		try {
    			launcher.run(job, new JobParametersBuilder().toJobParameters());
    		} catch (JobExecutionAlreadyRunningException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (JobRestartException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (JobInstanceAlreadyCompleteException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (JobParametersInvalidException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return "home";
    	}
    When i run this, I get ClassNotFoundExxception: org.springframework.dao.DuplicateKeyException

    First Question why so?

    Secondly i am using maven so added the dependency for spring-dao
    but there is no such class in that jar.

    Where am i wrong?
    Please help.
    Thanks.

  • #2
    Hi anuapmd,

    org.springframework.dao.DuplicateKeyException is a class from spring-tx which is a required dependency of spring batch. Add this as a maven dependency and it should work.

    Please see here for a full list of spring batch dependencies.

    Thanks,

    Phil

    Comment


    • #3
      Solved. thanks.
      Don't know which website i browsed and got that absurd solution.. thanks

      Comment


      • #4
        Also your code is flawed... If you want to run into database problems, memory and concurrency issues your code is correct but I assume those aren't issues you want to have nor want to solve.

        NEVER NEVER NEVER create an application context yourself when you need one. You are basically creating a new instance each time (you aren't reusing one). Use dependency injection to get access to your beans (inject the job launcher) and the job you want to launch. (Or make your bean implement ApplicationContextAware if you really want to get the dependencies instead of using dependency injection)

        Comment


        • #5
          Thank you so much for pointing out the mistake. I am still a very basic learner. But please can u point out where i am wrong.
          See I am using webapp-config.xml which is loaded in contextparam in web.xml. It contains all the beans. So they are loaded just once.
          Now to access those beans e.g(joblauncher) i ve used application context. I this what you are talking about?

          Thanks,
          Anupam

          Comment


          • #6
            See I am using webapp-config.xml which is loaded in contextparam in web.xml. It contains all the beans. So they are loaded just once.
            No thay aren't loaded once, they are loaded each time you create a new ApplicationContext which is the first thing you do in your controller method.

            Code:
            @RequestMapping(value = "/",method = RequestMethod.GET)
            	public String home(Locale locale, Model model) {
            		ApplicationContext ctx=new ClassPathXmlApplicationContext("/webapp-config.xml");
            		Job job=new SimpleJob("myjob1");
            		JobLauncher launcher=ctx.getBean(JobLauncher.class);
            		try {
            			launcher.run(job, new JobParametersBuilder().toJobParameters());
            		} catch (JobExecutionAlreadyRunningException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		} catch (JobRestartException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		} catch (JobInstanceAlreadyCompleteException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		} catch (JobParametersInvalidException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		}
            		return "home";
            	}
            As mentioned use dependency injection to inject the launched and the job to execute.

            Comment


            • #7
              Thank u. I got your point.
              One question again. Can I use @Autowired ? So the context won't be created again.

              Comment


              • #8
                Use whatever you want to get access the beans. Setter injection, @Autowired, @Inject, @Resource pick one...

                Comment

                Working...
                X