Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse, Tomcat, Maven, Spring MVC, Mongo (and insanity)

I've been trying to get a completely bare-bones Eclipse project running under Tomcat (launched by Eclipse) that makes use of Maven, Spring MVC, and Mongo. I have read several articles and attempted the tutorials I have found however, something has always caused an exception and the exercise comes to naught. I have spent quite some time going over my options and attempting to put this project together and my latest attempt was to create a maven-archtype-webapp from inside Eclipse.

After I've created the project, I set it up to run under Tomcat 7. Then I modify my pom file to add Spring MVC and Mongo DB functionality:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>springTest</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>springTest Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <spring.version>3.2.3.RELEASE</spring.version>
        <jdk.version>1.6</jdk.version>
        <spring-mongo.version>1.2.2.RELEASE</spring-mongo.version>
    </properties>    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>${spring-mongo.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>springTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <url>http://localhost:8080/manager/text</url>
                    <server>my-tomcat</server>
                    <path>/SampleSpringMaven</path>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

As far as code, the app only has 3 classes: springTest.model.Person, and springTest.service.PersonService, and springTest.controller.PersonController. Here's the code for each: package springTest.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
public class Person { 
    @Id
    private String id;
    private String name;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

package springTest.service;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;
import springTest.model.Person;

@Repository
public class PersonService {
@Autowired
protected MongoTemplate mongoTemplate;

public static final String COLLECTION_NAME = "person";

public void addPerson(Person person) {
    if (!mongoTemplate.collectionExists(Person.class)) {
        mongoTemplate.createCollection(Person.class);
    }
        person.setId(UUID.randomUUID().toString());
        mongoTemplate.insert(person, COLLECTION_NAME);
    }
    public List<Person> listPerson() {
        return mongoTemplate.findAll(Person.class, COLLECTION_NAME);
    }
    public void deletePerson(Person person) {
        mongoTemplate.remove(person, COLLECTION_NAME);
    }
    public void updatePerson(Person person) {
        mongoTemplate.insert(person, COLLECTION_NAME);
    }
}

package springTest.service;

import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;
import springTest.model.Person;

@Repository
public class PersonService {
    @Autowired
    protected MongoTemplate mongoTemplate;

    public static final String COLLECTION_NAME = "person";

    public void addPerson(Person person) {
        if (!mongoTemplate.collectionExists(Person.class)) {
            mongoTemplate.createCollection(Person.class);
        }
        person.setId(UUID.randomUUID().toString());
        mongoTemplate.insert(person, COLLECTION_NAME);
    }

    public List<Person> listPerson() {
        return mongoTemplate.findAll(Person.class, COLLECTION_NAME);
    }

    public void deletePerson(Person person) {
        mongoTemplate.remove(person, COLLECTION_NAME);
    }

    public void updatePerson(Person person) {
        mongoTemplate.insert(person, COLLECTION_NAME);
    }
}

Lastly, here's the exception I get when I start the app:

Mar 6, 2014 8:57:52 AM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:springTest' did not find a matching property.
Mar 6, 2014 8:57:52 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Mar 6, 2014 8:57:52 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Mar 6, 2014 8:57:52 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 484 ms
Mar 6, 2014 8:57:52 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Mar 6, 2014 8:57:52 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.42
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Mar 6, 2014 8:57:54 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Mar 6, 2014 8:57:55 AM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.springframework.data.mongodb.core.MongoTemplate springTest.service.PersonService.mongoTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.IllegalAccessError: tried to access method org.springframework.core.GenericTypeResolver.getTypeVariableMap(Ljava/lang/Class;)Ljava/util/Map; from class org.springframework.data.util.ClassTypeInformation
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: protected org.springframework.data.mongodb.core.MongoTemplate springTest.service.PersonService.mongoTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.IllegalAccessError: tried to access method org.springframework.core.GenericTypeResolver.getTypeVariableMap(Ljava/lang/Class;)Ljava/util/Map; from class org.springframework.data.util.ClassTypeInformation
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
    ... 23 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.IllegalAccessError: tried to access method org.springframework.core.GenericTypeResolver.getTypeVariableMap(Ljava/lang/Class;)Ljava/util/Map; from class org.springframework.data.util.ClassTypeInformation
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:844)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
    ... 25 more
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.IllegalAccessError: tried to access method org.springframework.core.GenericTypeResolver.getTypeVariableMap(Ljava/lang/Class;)Ljava/util/Map; from class org.springframework.data.util.ClassTypeInformation
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:108)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:280)
    ... 37 more
Caused by: java.lang.IllegalAccessError: tried to access method org.springframework.core.GenericTypeResolver.getTypeVariableMap(Ljava/lang/Class;)Ljava/util/Map; from class org.springframework.data.util.ClassTypeInformation
    at org.springframework.data.util.ClassTypeInformation.<init>(ClassTypeInformation.java:96)
    at org.springframework.data.util.ClassTypeInformation.<clinit>(ClassTypeInformation.java:42)
    at org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper.<clinit>(DefaultMongoTypeMapper.java:45)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.<init>(MappingMongoConverter.java:107)
    at org.springframework.data.mongodb.core.MongoTemplate.getDefaultMongoConverter(MongoTemplate.java:1687)
    at org.springframework.data.mongodb.core.MongoTemplate.<init>(MongoTemplate.java:189)
    at org.springframework.data.mongodb.core.MongoTemplate.<init>(MongoTemplate.java:175)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126)
    ... 39 more
Mar 6, 2014 8:57:55 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
Mar 6, 2014 8:57:55 AM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/springTest] startup failed due to previous errors
Mar 6, 2014 8:57:55 AM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Mar 6, 2014 8:57:55 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Mar 6, 2014 8:57:55 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Mar 6, 2014 8:57:55 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2131 ms

I left out the xml files, sorry: web.xml

<web-app 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"
    version="2.5">

    <display-name>Sample Spring Maven Project</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>  

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
    xsi:schemaLocation="
    http://www.springframework.org/schema/data/mongo
    http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <!-- Scans the classpath of Components to auto-detect -->
    <context:component-scan use-default-filters="false" base-package="springTest">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>

    <mongo:mongo host="127.0.0.1" port="27017" write-concern="JOURNAL_SAFE">
        <mongo:options connections-per-host="50"
                   threads-allowed-to-block-for-connection-multiplier="4"
                   connect-timeout="1000"
                   max-wait-time="1500"
                   auto-connect-retry="true"
                   socket-keep-alive="true"
                   socket-timeout="1500"
                   slave-ok="true"
                   write-number="1"
                   write-timeout="0"
                   write-fsync="false"/>
    </mongo:mongo>

    <mongo:db-factory mongo-ref="mongo" dbname="test" username="admin" password="password" />

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    </bean>

    <bean id="personController" class="springTest.controller.PersonController" />
    <bean id="personService" class="springTest.service.PersonService" />
    <bean id="person" class="springTest.model.Person" />

    <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
</bean>
</beans>  

I really need to understand why this fails the way it does (with an IllegalAccessError on a method in a MongoTemplate object). Are my version numbers for dependencies messing this up? I just can't figure out what's going on.

Regards,

Tim

like image 980
Tim Manchester Avatar asked Nov 10 '22 11:11

Tim Manchester


1 Answers

I can see your DB factory ref is 'mongo'. But in the mongoTemplate bean you have given ref to DB factory as mongoDbFactory. That could be why the bean mongoTemplate is unable to get created.

like image 108
shnr33 Avatar answered Nov 14 '22 21:11

shnr33