3

I'm facing the same issue as mentioned in the link: Mongo spring-data issue with java.util.Currency I tried the accepted answer. But its not working and i'm getting NullPointerException at line:

new CustomConversions(Arrays.asList(currencyToString, stringToCurrency));

So i defined converters in new classes, like this:

@Component
public class CurrencyToStringConverter implements Converter<Currency,String>{

    /* (non-Javadoc)
     * @see com.fasterxml.jackson.databind.util.Converter#convert(java.lang.Object)
     */
    @Override
    public String convert(Currency arg0) {
        System.out.println("***INSIDE CurrencyToStringConverter***"+arg0);
        return arg0.getCurrencyCode();
    }
  }

and

@Component
public class StringToCurrencyConverter implements Converter<String,Currency>{
/* (non-Javadoc)
 * @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
 */
    @Override
    public Currency convert(String arg0) {
        System.out.println("***INSIDE StringToCurrencyConverter***"+arg0);
        return Currency.getInstance(arg0);
    }
}

I used them in "customConversions()" as shown below:

@Configuration
public class CustomMongoConfiguration extends AbstractMongoConfiguration {
    @Autowired
    private Environment env;

    @Bean
  @Override
  public CustomConversions customConversions() {
      System.out.println("***CUSTOM MONGO CONVERSIONS***");
    List<Converter<?,?>> converters=new ArrayList<>();
    converters.add(new CurrencyToStringConverter());
    converters.add(new StringToCurrencyConverter());

    return new CustomConversions(converters);
  }

    /* (non-Javadoc)
     * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#getDatabaseName()
     */
    @Override
    protected String getDatabaseName() {
        // TODO Auto-generated method stub
        String prop = env.getProperty("spring.data.mongodb.database");
        System.out.println("database naem:: "+prop);
        return prop;
    }

    /* (non-Javadoc)
     * @see org.springframework.data.mongodb.config.AbstractMongoConfiguration#mongo()
     */
    @Override
    @Bean
    public Mongo mongo() throws Exception {
        String prop = env.getProperty("spring.data.mongodb.host");
        System.out.println("host naem:: "+prop);
        return new MongoClient(prop);
    }
}

When spring-boot application starts up, i could see below statments printed:

System.out.println("***CUSTOM MONGO CONVERSIONS***");
System.out.println("database naem:: "+prop);
System.out.println("host naem:: "+prop);

But when i try to get my object from MongoDB, it never calls "convert" methods in Converter classs and moreover, i always get this exception:

org.springframework.data.mapping.model.MappingException: No property null found on entity class java.util.Currency to bind constructor parameter to!
    at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:74)
    at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:63)
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:71)
    at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:251)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1186)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$200(MappingMongoConverter.java:78)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1134)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.getValueInternal(MappingMongoConverter.java:870)

I followed this link too:

Spring not using mongo custom converters

I changed @Configuration annotation to @Component in the class,CustomMongoConfiguration,as suggested in the link. But Its also not working. If i use @Component annotation, below statements are getting printed multiple times. I dont know the reason.

System.out.println("***CUSTOM MONGO CONVERSIONS***");
System.out.println("database naem:: "+prop);
System.out.println("host naem:: "+prop);

I'm using spring-boot version 1.3.2.RELEASE.

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
</parent>

By the way, i'm using application.properties to configure mongodb properties but not any java based configuration:

spring.data.mongodb.host=localhost
spring.data.mongodb.password=
spring.data.mongodb.port=27017
spring.data.mongodb.repositories.enabled=true
spring.data.mongodb.database=abcde

I'm struggling to solve this for the past three days. Can anyone please help me out.

Community
  • 1
  • 1
kaluva
  • 621
  • 8
  • 27

2 Answers2

2

Currency conversion has been added via b7131b and is available as of 1.9.0.M1.

Please add @ReadingConverter and @WritingConverter to your Converter implementations so that CustomConversions and not only the underlying ConversionService is aware of those.

Christoph Strobl
  • 6,491
  • 25
  • 33
  • Nope. Its not working. Getting same error `org.springframework.data.mapping.model.MappingException: No property null found on entity class java.util.Currency to bind constructor parameter to! at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:74) ` – kaluva Mar 16 '16 at 15:43
  • I have a doubt. Do i need to call Converter's "convert" methods anywhere in my code. I'm thinking, those will be called automatically. Correct me if i'm wrong? – kaluva Mar 16 '16 at 15:44
2

My Bad. Problem is with the data which was inserted earlier in mongodb. Earlier inserted in mongodb with improper "currency" format ie., instead of just string value like USD, GBP it has below structure:

"currency" : {
                        "currencyCode" : "GBP",
                        "defaultFractionDigits" : 2,
                        "numericCode" : 826
                }

instead of simple code like:

 "currency" : "GBP"

After i wrote converters, mongo unable to parse this structure and throwing this exception:

org.springframework.data.mapping.model.MappingException: No property null found on entity class java.util.Currency to bind constructor parameter to!
    at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:74)

I think this exception is misleading. Anyways, i figured it out. Now both converters are being called.

Final Solution that worked for me:

@Configuration
public class CustomMongoConfiguration extends AbstractMongoConfiguration {
    @Autowired
    private MongoProperties mongoProps;

    @Bean
    @Override
    public CustomConversions customConversions() {
        System.out.println("***CUSTOM MONGO CONVERSIONS***");
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(new CurrencyToStringConverter());
        converters.add(new StringToCurrencyConverter());

        return new CustomConversions(converters);
    }

    @Override
    protected String getDatabaseName() {
        return mongoProps.getDatabase();
    }

    @Override
    @Bean
    public Mongo mongo() throws Exception {
        return new MongoClient(mongoProps.getHost(), mongoProps.getPort());
    }
}

As per spring docs, http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.converter-disambiguation, you need to put @ReadingConverter and @WritingConverter on converters only if both source & target are native types (for ex: String to Long or Long to String). Otherwise, you don't need to have them on converters. In my case those not required as Currency is not native mongo type.

kaluva
  • 621
  • 8
  • 27