0

Currently, I am facing a problem with Spring authentication with MongoDB. I have the following declaration in my Spring XML configuration file:

Spring Boot Importing of Spring XML file: I am importing the below "spring configuration XML" file in my "spring boot main class" as follows:

@SpringBootApplication
@ImportResource("classpath:META-INF/spring/Myapp-AppContext.xml")
public class MySpringBootApplication extends SpringBootServletInitializer {
.... //Some Code goes here
}

Spring Configuration XML File:

<mongo:mongo-client id="mongo" host="localhost" port="27017" credentials="admin:mypass@mydb">       
    <mongo:client-options description="Connection to DB"/>
</mongo:mongo-client>

<mongo:db-factory id="myConnection" mongo-ref="mongo" dbname="mydb"/>
<mongo:template id="myOps" db-factory-ref="myConnection"/>
<mongo:repositories
    base-package="com.test.app" mongo-template-ref="myOps" />

While running it as a "Spring Boot Application", I am getting the following error:

Exception:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'com.mongodb.MongoCredential[]' for property 'credentials'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.mongodb.MongoCredential' for property 'credentials[0]': no matching editors or conversion strategy found at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1658) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1614) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1361) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578) ~[spring-beans-5.0.6.RELEASE.jar:5.0.6.RELEASE] ... 118 common frames omitted

Exception Reason:

As per my understanding, I believe the "Spring-data-Mongodb" JAR is missing a "Converter" implementation that converts the "credentials" attribute(It's a String type) to a "com.mongodb.MongoCredential" array.

Please let me know whether there is another enterprise version of the "spring-data-mongodb" which does support the authentication mechanism Or any other way of resolving this issue are welcome.

My Application uses the following versions of the software:

  • Spring Boot version Used: 2.0.2.RELEASE
  • Spring version Used: 5.0.6.RELEASE
  • Spring data MongoDB Version: 2.0.9.RELEASE
  • Mongo Driver version: 3.8.0
  • Mongo Java Driver version: 3.8.0
  • Mongo Driver Core version: 3.8.0 (Used alternatively with Mongo Java Driver JAR, as they are same)
  • Mongo Community Server version: 3.6.5
4
  • please paste the code that how you import the spring xml file Commented Aug 19, 2018 at 14:46
  • I updated my "question section", on how I am importing the "spring xml" file to my "spring boot main class". I am packaging this application as an WAR and deploying it to Tomcat. Therefore my spring boot class is extending the "SpringBootServletInitializer" class. Commented Aug 19, 2018 at 22:17
  • can you paste the code of MySpringBootApplication? Commented Aug 20, 2018 at 1:27
  • Can you share a project to run that shows the issue. SD-MongoDB has a dedicated MongoCredentialPropertyEditor that takes care of converting the credentials string. Commented Aug 21, 2018 at 9:36

3 Answers 3

2

I made it working in a different way. Here, is the final Spring XML file configuration looks like:

<bean id="myMongoServers" class="java.util.ArrayList">
<constructor-arg>
    <list>
        <ref bean="myMongoServer" />
    </list>
</constructor-arg>
</bean>

<bean id="myMongoServer" class="com.mongodb.ServerAddress">
        <constructor-arg type="java.lang.String" name="host" value="localhost" />
        <constructor-arg type="int" name="port" value="27017" />
</bean>

<bean id="myMongoCredentials" class="java.util.ArrayList">
<constructor-arg>
    <list>
        <ref bean="myMongoCredential" />
    </list>
</constructor-arg>
</bean>

<bean id="myMongoCredential" class="com.mongodb.MongoCredential">
        <constructor-arg name="mechanism" value = "#{T(com.mongodb.AuthenticationMechanism).SCRAM_SHA_1}" />
        <constructor-arg type="java.lang.String" name="userName" value="admin" />
        <constructor-arg type="java.lang.String" name="source" value="mydb" />
        <constructor-arg type="char[]" name="password" value="mypass"/>
</bean>

<!-- MongoClient -->
<bean id="mongo" class="com.mongodb.MongoClient">
        <constructor-arg ref="myMongoServers" />
        <constructor-arg ref="myMongoCredentials"  />
</bean>

<mongo:db-factory id="myConnection" mongo-ref="mongo" dbname="mydb"/>

<mongo:template id="myOps" db-factory-ref="myConnection"/>

<mongo:repositories base-package="com.test.app" mongo-template-ref="myOps" />
Sign up to request clarification or add additional context in comments.

Comments

0

This issue is due to changes in the way credentials were passed to mongo-driver. With this, you need to supply ServerAddress and Credentials (part of which is password which is taken as Character[]).

SCRAM-SHA-1 is the mechanism used for authenticating to MongoDB. If you want, there are other method for different authentication with similar parameters.

If you are using Java based config, you can refer this snippet:

    @Bean
    public MongoDbFactory mongoDbFactory() {
        ServerAddress serverAddress = new ServerAddress(mongoHost, mongoPort);
        MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(mongoUser, mongoDB, mongoPass.toCharArray());

        MongoClient mongoClient = new MongoClient(serverAddress, mongoCredential,
                new MongoClientOptions.Builder().build());
        MongoDbFactory dbFactory = new SimpleMongoDbFactory(mongoClient, mongoDB);
        return dbFactory;
    }

    @Bean
    public MongoTemplate mongoTemplate(@Autowired MongoDbFactory mongoDbFactory) {
        return new MongoTemplate(mongoDbFactory);
    }

Refer this: http://mongodb.github.io/mongo-java-driver/3.6/javadoc/?com/mongodb/MongoCredential.html

Comments

0

Spring xml configuraton

<bean   id="mongoServer1" class="com.mongodb.ServerAddress">
    <constructor-arg    type="java.lang.String" name="host" value="190.6.5.167"/>
    <constructor-arg    type="int"  name="port" value="27017"/>
</bean>
<bean   id="mongoServer2" class="com.mongodb.ServerAddress">
    <constructor-arg    type="java.lang.String" name="host" value="190.6.5.168"/>
    <constructor-arg    type="int"  name="port" value="27017"/>
</bean>
<bean   id="mongoServer3" class="com.mongodb.ServerAddress">
    <constructor-arg    type="java.lang.String" name="host" value="190.6.5.169"/>
    <constructor-arg    type="int"  name="port" value="27017"/>
</bean>
<bean   id="mongoServers" class="java.util.ArrayList">
    <constructor-arg>
        <list>
            <ref    bean="mongoServer1"/>
            <ref    bean="mongoServer2"/>
            <ref    bean="mongoServer3"/>
        </list>
    </constructor-arg>
</bean>
<bean id="mongoCredential" class="com.mongodb.MongoCredential" factory-method="createCredential"> 
    <constructor-arg    type="java.lang.String" name="userName" value="adminuser"/>
    <constructor-arg    type="java.lang.String" name="database" value="testdb"/>
    <constructor-arg    type="char[]"   name="password" value="adminpass"/>
</bean>
<bean id="mongoClientOptions" class="org.demo.helper.mongo.MongoClientOptionBuilderHelper"
    factory-method="createMongoClientOptions">
    <constructor-arg type="int" name="minConnectionsPerHost"    value="60"/>
    <constructor-arg type="int" name="threadsAllowedToBlockForConnectionMultiplier" value="10"/>
    <constructor-arg type="int" name="connectTimeout"   value="60000"/>
    <constructor-arg type="int" name="socketTimeout"    value="60000"/>
    <constructor-arg type="boolean" name="socketKeepAlive"  value="true"/>
</bean>
<bean id="mongoClient" class="com.mongodb.MongoClient">
    <constructor-arg    name="seeds"    ref="mongoServers"/>
    <constructor-arg    name="credential"   ref="mongoCredential"/>
    <constructor-arg    name="options"  ref="mongoClientOptions"/>
</bean>

Helper Class

package org.demo.helper.mongo;

import com.mongodb.MongoClientOptions;

public class MongoClientOptionBuilderHelper {

    private static MongoClientOptions mongoClientOptions = null;

    public static MongoClientOptions createMongoClientOptions(int minConnectionsPerHost,
            int tatbfcm, int connectTimeout, int socketTimeout,
            boolean socketKeepAlive) {
        if (mongoClientOptions == null) {
            synchronized (MongoClientOptionBuilderHapler.class) {
                if (mongoClientOptions == null) {
                    mongoClientOptions = MongoClientOptions
                    .builder()
                    .minConnectionsPerHost(minConnectionsPerHost)
                    .threadsAllowedToBlockForConnectionMultiplier(tatbfcm) 
                    .connectTimeout(connectTimeout)
                    .socketTimeout(socketTimeout)
                    //...
                    //...
                    //...
                    .socketKeepAlive(socketKeepAlive)
                    .build();
                }
            }
        }
        return mongoClientOptions;
    }

}

Mongo Java Driver Version

<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.0</version>
</dependency>

Spring Core Version

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.