Inject date using #Value annotation - spring

This is how I am trying to inject a date into a #Component class.
#Value("${new java.text.SimpleDateFormat(\"yyyyMMdd\").parse(\"${PROP_DATE}\")}")
Date myDate;
The date is specified as a String in properties file :
PROP_DATE=20110421
I get this error. What am I doing wrong? Is there any other way to inject Date property? Thanks.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ccc': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: java.util.Date aaa.bbb.ccc.myDate; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'new java.text.SimpleDateFormat("yyyyMMdd").parse("20110421")'

Use #{new java.text.SimpleDateFormat(\"yyyyMMdd\").parse(\"${PROP_DATE}\")} for process value with spEL

Related

Spring Data: Mongo Repository can not be initialized

I'm getting this strange error message when I start my spring boot service:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property storeMpi found for type Patient!
Service can't be started since this exception is raised.
My code is very straight:
public interface PatientRepository
extends MongoRepository<Patient, String>,
QuerydslPredicateExecutor<Patient>,
MPIPatientRepository
{
}
public interface MPIPatientRepository {
Patient storeMpi(Patient patient);
}
You can see, that storeMpi is a method, not an expected field of my Patient entity.
Implementation is straight as well:
#Repository
#RequiredArgsConstructor
public class MPIPatientRepository implements cat.gencat.catsalut.hes.mpi.repository.MPIPatientRepository {
private final MongoTemplate mongoTemplate;
/**
* {#inheritDoc}
*/
#Override
public Patient storeMpi(Patient patient) {
return this.mongoTemplate.save(patient);
}
I don't quite figure out what's wrong.
Formatted root CausedBy is:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ca.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$FhirRestfulServerConfiguration': Bean instantiation via constructor failed;
nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [ca.uhn.fhir.spring.boot.autoconfigure.FhirAutoConfiguration$FhirRestfulServerConfiguration$$EnhancerBySpringCGLIB$$5fe4b535]: Constructor threw exception;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'patientResourceProvider' defined in file [/home/jeusdi/projects/salut/mpi/hes-mpi-fhir-mongodb/target/classes/cat/gencat/catsalut/hes/mpi/providers/PatientResourceProvider.class]: Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'patientService' defined in file [/home/jeusdi/projects/salut/mpi/hes-mpi-fhir-mongodb/target/classes/cat/gencat/catsalut/hes/mpi/service/PatientService.class]: Unsatisfied dependency expressed through constructor parameter 2;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'patientRepository' defined in cat.gencat.catsalut.hes.mpi.repository.PatientRepository defined in #EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Invocation of init method failed;
nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract cat.gencat.catsalut.hes.mpi.model.Patient cat.gencat.catsalut.hes.mpi.repository.MPIPatientRepository.storeMpi(cat.gencat.catsalut.hes.mpi.model.Patient)! Reason: No property storeMpi found for type Patient!;
nested exception is org.springframework.data.mapping.PropertyReferenceException: No property storeMpi found for type Patient!
Any ideas?

Why creating been in Spring occurs with error?

Hello I am creating program which will communicate and send information using channel. When I run program it doesn't work.
Errors:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-05-02 13:47:37.938 ERROR 12584 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloWorldQueueProducer' defined in file [C:\workspace\target\classes\edu\producer\HelloWorldQueueProducer.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jmsTemplate' defined in class path resource [org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration$JmsTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'jmsTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryConfiguration$SimpleConnectionFactoryConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.jms.connection.CachingConnectionFactory]: Factory method 'cachingJmsConnectionFactory' threw exception; nested exception is java.lang.IllegalStateException: Unable to create ActiveMQConnectionFactory
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.5.jar:5.3.5]
#Component
#RequiredArgsConstructor
public class HelloWorldQueueProducer {
private final JmsTemplate jmsTemplate;
#Scheduled(fixedRate = 2000)
public void sendHello() {
HelloMessage message = HelloMessage.builder()
.id(HelloMessage.nextId())
.createdAt(LocalDateTime.now())
.message("Hello world!")
.build();
jmsTemplate.convertAndSend(JmsConfig.QUEUE_HELLO_WORLD, message);
System.out.println("HelloWorldQueueProducer.sendHello - sent message: " + message);
}
}
Not quite sure about it, but have you defined the necessary properties in your application.properties? You need to set them like this i. e.
spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=developer
spring.artemis.password=developer
jms.queue.destination=myqueue
Otherwise the autoconfiguration of spring boot wouldn't bootstrap the necessary beans. I had this problem once.

#Value annotation for reading Map from property file

My Java has this
#Value("#{${validators}}")
private Map<String,String> validators;
property file has this
validators={AlphabetValidator:'AlphabetValidator',NumberValidator:'NumberValidator'AlphaNumericValidator:'AlphaNumericValidator',DateValidator:'DateValidator', FixedLengthValidator:'FixedLengthValidator',MinimumLengthValidator:'MinimumLengthValidator',MaximumLengthValidator:'MaximumLengthValidator',CustomValidator:'CustomValidator' MandatoryFieldValidator: 'MandatoryFieldValidator',TimeValidator:'TimeValidator'}
when I run the app.. I am getting this error
Exception in thread "main"
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'validatorProperties': Unsatisfied
dependency expressed through field 'validators'; nested exception is
org.springframework.beans.factory.BeanExpressionException: Expression
parsing failed; nested exception is
org.springframework.expression.spel.SpelParseException: EL1041E:(pos
1): After parsing a valid expression, there is still more data in the
expression: 'lcurly({)'
Check out for comma ',' in property file.
Properties file:
validators={AlphabetValidator:'AlphabetValidator',NumberValidator:'NumberValidator',AlphaNumericValidator:'AlphaNumericValidator',DateValidator:'DateValidator',FixedLengthValidator:'FixedLengthValidator',MinimumLengthValidator:'MinimumLengthValidator',MaximumLengthValidator:'MaximumLengthValidator',CustomValidator:'CustomValidator',MandatoryFieldValidator:'MandatoryFieldValidator',TimeValidator:'TimeValidator'}
Java code:
#Value("#{${validators}}")
private Map<String,String> validators;
You have missed to specify some commas inside your properties. Try with following:
validators={AlphabetValidator:'AlphabetValidator',NumberValidator:'NumberValidator',AlphaNumericValidator:'AlphaNumericValidator',DateValidator:'DateValidator',FixedLengthValidator:'FixedLengthValidator',MinimumLengthValidator:'MinimumLengthValidator',MaximumLengthValidator:'MaximumLengthValidator',CustomValidator:'CustomValidator',MandatoryFieldValidator:'MandatoryFieldValidator',TimeValidator:'TimeValidator'}

grails cdn-asset-pipeline plugin

We are currently using grails cdn-asset-pipeline plugin. For pushing our assets into s3. The cdn-asset-pipeline plugin use loadApp() inside _AssetCdn.groovy. Which causes JNDI issues. The JNDI is available in our production tomcat. When we use grails run-app we are able to run our app without issues. Can you let me know what changes we can do to overcome this issue.
_AssetCdn.groovy:
target(loadConfig: "Load CDN assets config") {
depends(compile, parseArguments)
if (argsMap['help']) {
println USAGE
exit 0
}
loadApp()
configureApp()
initKarman()
providers = []
def cdnAssetsConfig = grailsApp.config.grails.assets?.cdn
providers = cdnAssetsConfig.providers ?: []
if (!providers) {
def providerObject = [:]
providerObject.provider = argsMap['provider'] ?: cdnAssetsConfig?.provider ?: ''
providerObject.directory = argsMap['directory'] ?: cdnAssetsConfig?.directory ?: ''
providerObject.accessKey = argsMap['access-key'] ?: cdnAssetsConfig?.accessKey ?: ''
providerObject.secretKey = argsMap['secret-key'] ?: cdnAssetsConfig?.secretKey ?: ''
providerObject.region = argsMap['region'] ?: cdnAssetsConfig?.region ?: ''
providers << providerObject
}
When we run, the below command before building the war
grails asset-cdn-push --provider=S3 --directory="my directory" --gzip=true --storage-path="storage path" --access-key="access key" --secret-key="secret key"
The Error:
| Error executing script AssetCdnPush: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with
name 'transactionManager': Cannot resolve reference to bean 'transactionManager_bonita' while setting constructor argument with key [2]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager_bonita': Cannot resolve reference to
bean 'sessionFactory_bonita' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory_bonita': Cannot resolve reference to bean 'dataSource_bonita' while setting bean property 'dataSource
'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource_bonita': Cannot resolve reference to bean 'dataSourceLazy_bonita' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSourceLazy_bonita': Cannot resolve reference to bean 'dataSourceUnproxied_bonita' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceUnproxied_bonita': Invocatio
n of init method failed; nested exception is javax.naming.NameNotFoundException: Name [java:comp/env/bonitaDS] not bound; 2 bindings: [bonitaSequenceManagerDS,bonitaDS]
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceUnproxied_bonita': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [java:comp/env/bonitaDS] not bound; 2 bindings: [bonitaSequenceManagerDS,
bonitaDS]
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceUnproxied_bonita': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [java:comp/env/bonitaDS] not bound; 2 bindings: [bonitaSequenceManagerDS,
bonitaDS]
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceUnproxied_bonita': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [java:comp/env/bonitaDS] not bound; 2 bindings: [bonitaSequenceManagerDS,
bonitaDS] (Use --stacktrace to see the full trace)

How to autowire mongoTemplate into custom type converter?

I'm trying to create a converter that will fetch object from DB by it's ObjectId. But the mongoTemplate is always empty in converter:
org.springframework.core.convert.ConversionFailedException:
Failed to
convert from type org.bson.types.ObjectId to type
com.atlas.mymodule.datadomain.MyObject for value
'130000000000000000000013';
nested exception is
java.lang.NullPointerException
Code:
#Component
public class ObjectIdToMyObjectConverter implements Converter<ObjectId, MyObject> {
#Autowired
private MongoTemplate mongoTemplate; // null ???
public MyObject convert(ObjectId objectId) {
return mongoTemplate.findById(objectId, MyObject.class); // <- NullPointerException
}
}
Configuration:
#Configuration
#ComponentScan
#EnableMongoRepositories
public abstract class MyModuleConfiguration extends AbstractMongoConfiguration {
#Override
public MongoClient mongo() throws Exception {
List<MongoCredential> mongoCredential = getMongoCredentials();
return mongoCredential == null ?
new MongoClient(getMongoServerAddresses()) :
new MongoClient(getMongoServerAddresses(), mongoCredential, getMongoClientOptions());
}
protected abstract List<MongoCredential> getMongoCredentials();
protected abstract MongoClientOptions getMongoClientOptions();
protected abstract List<ServerAddress> getMongoServerAddresses() throws UnknownHostException;
#Bean
public ObjectIdToMyObjectConverter objectIdToMyObjectConverter() {
return new ObjectIdToMyObjectConverter());
}
#Override
public CustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
converters.add(objectIdToMyObjectConverter());
return new CustomConversions(converters);
}
}
Test Configuration:
public class MyModuleTestConfiguration extends MyModuleConfiguration {
// overrides abstract methods, defines connection details...
}
update:
I've updated the code according to #mavarazy suggestion (added ObjectIdToMyObjectConverter bean definition) but got an exception:
Error creating bean with name 'mongoTemplate': Requested bean is
currently in creation: Is there an unresolvable circular reference?
Full exception:
Error creating bean with name 'mongoTemplate' defined in com.atlas.MyModule.MyModuleTestConfiguration:
Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.data.mongodb.core.MongoTemplate]: Factory method 'mongoTemplate' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mappingMongoConverter' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.data.mongodb.core.convert.MappingMongoConverter]: Factory method 'mappingMongoConverter' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'mongoMappingContext' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.data.mongodb.core.mapping.MongoMappingContext]: Factory method 'mongoMappingContext' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'customConversions' defined in com.atlas.MyModule.MyModuleTestConfiguration: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.data.mongodb.core.convert.CustomConversions]: Factory method 'customConversions' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'objectIdToMyObjectConverter': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.springframework.data.mongodb.core.MongoTemplate com.atlas.MyModule.ObjectIdToMyObjectConverter.mongoTemplate;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'mongoTemplate': Requested bean is currently in creation: Is there an unresolvable circular reference?
Thanks.
ObjectIdToMyObjectConverter is not a spring bean. If you want #Autowired to work, create ObjectIdToMyObjectConverter as Spring bean, like this:
#Bean
public ObjectIdToMyObjectConverter objectIdToMyObjectConverter() {
return new ObjectIdToMyObjectConverter());
}
and #Autowire it in your configuration.
Following #Savash update
I have not paid enough attention to your configurations.
What you see is happening because you are trying to create MongoTemplate, which depends on CustomConversions, and at the same time CustomConversions depend on MongoTemplate, spring can't and should not do that.
As a solution:
You can create your CustomConversions with ApplicationContextAware, and extract MongoTemplate reference lazily on a first call.
I thought you are using CustomConversions as part of spring-integration or something. If so it does not need to be part of converters for Mongo. If you need it as MongoConverters, you are doing something really strange.
What is exact use case, you need this for?
Following comments:
Do I understand right, that you want MongoTemplate to read object with user reference as User object, and write object with User value as user reference?
I think.
You have a bad data model (you are trying to emulate JOIN operation in your MongoTemplate, which means you are missing something in your data model, and this is not how you should work with mongo).
Just call User explicitly when you need it, don't overload your DB with additional work, you'll have problems with performance
You can use another object, which you'll enrich with current user, as needed
Maybe SQL & ORM like Hibernate is a better approach for you ?
Try Hibernate OGM for your purpose, it might provide functionality, you need (Not sure, though, have not worked with it)

Resources