java.lang.IllegalArgumentException: Invalid boolean #Value("${com.test.isTestEnable") - spring-boot

I am getting
**Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Boolean'; nested exception is java.lang.IllegalArgumentException: **
I believe this happens due to missing spring place holder config. But I have the bean initialised in application context and still getting this error. Can any one help me out??
#Value("${com.test.isTestEnable")
public Boolean isTestEnable;
Spring Properties Class
public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {
private static HashMap<String, String> systemPropertiesMap;
private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
public static String getProperty(final String name) {
return systemPropertiesMap.get(name);
}
#Override
protected void processProperties(final ConfigurableListableBeanFactory beanFactory, final Properties props) throws BeansException {
super.processProperties(beanFactory, props);
systemPropertiesMap = new HashMap<String, String>();
for (final Object key : props.keySet()) {
final String keyStr = key.toString();
final String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
systemPropertiesMap.put(keyStr, valueStr);
}
}
#Override
public void setSystemPropertiesMode(final int systemPropertiesMode) {
super.setSystemPropertiesMode(systemPropertiesMode);
springSystemPropertiesMode = systemPropertiesMode;
}
my application-context file
<bean id="placeholderConfig" class="com.test.SpringPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>file:${config.path}/application.properties</value>
<value>file:${config.path}/log.properties</value>
</list>
</property>
</bean>

Your real issue was just a typo at #Value("${com.test.isTestEnable") - you're missing a closing curly bracket } at the end of the expression
This should work completely fine:
#Value("${com.test.isTestEnable}")
public Boolean isTestEnable;

Try changing the following line
#Value("${com.test.isTestEnable")
to
#Value("#{new Boolean('${com.test.isTestEnable}')}")
OR
#Value("#{T(Boolean).parseBoolean('${com.test.isTestEnable}')}")

Related

Spring mvc messagesource failed in annotation

I am able to retrieve message with this code
public class UserApp {
public static void main(String[] args) {
ApplicationContext appContext
= new ClassPathXmlApplicationContext("application-configuration.xml");
System.out.println(appContext.getMessage("NotEmpty.userForm.name",
new Object[] { 28,"http://www.mkyong.com" }, Locale.US ));
}
}
But failed with the same application-configuration.xml using ContextConfiguration Annotation. it is showing me
Caused by: org.springframework.context.NoSuchMessageException: No message found under code 'NotEmpty.userForm.name' for locale 'en_US'.
#Controller
#ContextConfiguration("/application-configuration.xml")
public class UserController {
private static final Logger logger =
LoggerFactory.getLogger(UserController.class);
#Autowired
ApplicationContext appContext;
#RequestMapping(value = "/users/add", method = RequestMethod.GET)
public String showAddUserForm(Model model) {
String temp = appContext.getMessage("NotEmpty.userForm.name",
new Object[] { 28,"http://www.mkyong.com" }, Locale.US ));
}
}
application-configuration.xml
<beans:bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename">
<beans:value>locale/messages</beans:value>
</beans:property>
</beans:bean>
Did i use the wrong annotation for this?

CustomPropertyEditor is not working

I am new to Spring. I am trying implementing CustomPropertyEditor using PropertyEditorSupport and registering the CustomPropertyEditor in app-context.xml.
Please find the code below.
public class NamePropertyEditor extends PropertyEditorSupport{
#Override
public void setAsText(String text) throws IllegalArgumentException {
//String[] name = text.split(":");
System.out.println("text: "+ text);
Name result = new Name(text, "randomString");
setValue(result);
}
}
app-context file
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.property.bean.Name">
<bean class="com.property.editor.NamePropertyEditor"/>
</entry>
</map>
</property>
</bean>
<bean id="exampleBean" class="com.start.CustomEditorExample">
<property name="name">
<value>Varun Bhatia</value></property>
</bean>
Class trying to use PropertyEditor
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:/META-INF/spring/app-context.xml");
//ctx.refresh();
CustomEditorExample bean = (CustomEditorExample) ctx.getBean("exampleBean");
System.out.println(bean.getName());
}
public Name getName() {
System.out.println("getName");
return name;
}
public void setName(Name name) {
System.out.println("setName");
this.name = name;
}
Problem is control is not going to setAsText method.
Code that you have written in main() will not invoke your property editor
Try something like
CustomEditorExample bean = (CustomEditorExample) ctx.getBean("exampleBean");
BeanWrapper wrapper = new BeanWrapperImpl(bean );
wrapper.setPropertyValue("name", "Some Text");//this will invoke your property editor
System.out.println(bean.getName());
I would advise you to read this Spring Docs

PropertyPlaceholderConfigurer: Use external properties file

How to configure PropertyPlaceholderConfigurer to use properties files relative (some directories up) to the war?
We have running a war multiple times and each war should read its configuration for example from ../../etc/db.properties.
Update:
Yes, the properties files are outside the war. The directory structure is:
/htdocs/shop/live/apache-tomat/webapps/shop.war
should read
/htdocs/shop/live/etc/db.properties
and
/htdocs/shop/test/apache-tomat/webapps/shop.war
should read
/htdocs/shop/test/etc/db.properties
Finally, we have introduced a new resource type "relative:":
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>relative:../../../etc/db.properties</value>
</list>
</property>
</bean>
We have extended XmlWebApplicationContext to inject custom resource handling:
public class Context extends XmlWebApplicationContext {
#Override
public Resource getResource(String location) {
if (location.startsWith(RelativeResource.RELATIVE_URL_PREFIX)) {
String relativePath = location.substring(RelativeResource.RELATIVE_URL_PREFIX.length());
return new RelativeResource(getServletContext(), relativePath);
}
return super.getResource(location);
}
}
Here is the relative resource class:
public class RelativeResource extends AbstractResource {
public static final String RELATIVE_URL_PREFIX = "relative:";
private final ServletContext servletContext;
private final String relativePath;
public RelativeResource(ServletContext servletContext, String relativePath) {
this.servletContext = servletContext;
this.relativePath = relativePath;
}
#Override
public String getDescription() {
return "RelativeResource [" + relativePath + "]";
}
#Override
public boolean isReadable() {
return true;
}
#Override
public boolean isOpen() {
return true;
}
#Override
public InputStream getInputStream() throws IOException {
String rootPath = WebUtils.getRealPath(servletContext, "/");
if (!rootPath.endsWith(File.separator)) rootPath += File.separator;
String path = rootPath + relativePath;
return new FileInputStream(path);
}
}
My code, based on mazatwork solution:
public class RelativeResource extends AbstractResource {
private final String relativePath;
public RelativeResource(String relativePath) {
this.relativePath = relativePath;
}
#Override
public String getDescription() {
return "RelativeResource [" + relativePath + "]";
}
#Override
public boolean isReadable() {
File resourceFile = new File(getAbsoluteFileLocation());
return resourceFile.exists();
}
#Override
public boolean isOpen() {
return true;
}
#Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(getAbsoluteFileLocation());
}
private String getAbsoluteFileLocation() {
return Paths.get("").toAbsolutePath().resolve(relativePath).toString();
}
}
After that we can write in xml for example:
<bean id="configurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value type="com.blabla.RelativeResource">overrideProperties.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>
Pros of this method - you don't hack Spring Context and don't stick to this hacked context implementation, you can use any (for example, not XmlWebApplicationContext, but ClassPathXmlApplicationContext) from Spring distribution.
In your configuration you can specify the properties from the classpath instead of relative to the configuration file.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
For this to work you must make sure that the properties file makes it to the classpath.
Somehow I wasn't able to get the desired path following others' methods, so here is my working version, based primarily on Dmitry's answer (usage in xml is identical), while isReadable() and getInputStream() looks more like mazatwork's version:
public class RelativeResource extends AbstractResource {
private final String relativePath;
public RelativeResource(String relativePath) {
this.relativePath = relativePath;
}
#Override
public String getDescription() {
return "RelativeResource [" + relativePath + "]";
}
#Override
public boolean isReadable() {
return true;
}
#Override
public boolean isOpen() {
return true;
}
#Override
public InputStream getInputStream() throws IOException {
String rootPath = this.getClass().getResource("/").getPath();
rootPath = URLDecoder.decode(rootPath, "UTF-8");
if (!rootPath.endsWith(File.separator)) rootPath += File.separator;
String path = rootPath + relativePath;
return new FileInputStream(path);
}
}

Spring doesn't use my Conerverter. Why?

I have custom Converter:
public class DateTimeConverter implements Converter<String, DateTime> {
private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
private DateTimeFormatter formatter;
private String datePattern = DEFAULT_DATE_PATTERN;
public String getDatePattern() {
return datePattern;
}
#Autowired(required = false)
public void setDatePattern(String datePattern) {
this.datePattern = datePattern;
}
#PostConstruct
public void init() {
formatter = DateTimeFormat.forPattern(datePattern);
}
#Override
public DateTime convert(String source) {
if (source == null) return new DateTime();
return formatter.parseDateTime(source);
}
}
And field in JavaBean:
#NotNull
#Column(name = "dateandtime")
private DateTime dateAndTime;
I registered my converter in setting:
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.myapp.util.DateTimeConverter"/>
</list>
</property>
</bean>
I got this exception:
Failed to convert property value of type 'java.lang.String' to required type 'org.joda.time.DateTime' for property 'dateAndTime'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.joda.time.DateTime] for property 'dateAndTime': no matching editors or conversion strategy found
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("file:src/main/resources/spring/business-config.xml")
public class JdbcTransactionRepositoryImplTest extends TestCase {
private static final Logger logger = Logger.getLogger(JdbcTransactionRepositoryImplTest.class);
#Autowired
private ApplicationContext context;
private JdbcTransactionRepositoryImpl transactionRepository;
#Before
public void setup() {
transactionRepository = new JdbcTransactionRepositoryImpl((DataSource) context.getBean("dataSource"));
}
#Test
public void testFindById() throws Exception {
Transaction tr1 = transactionRepository.findById(1);
assertEquals(new Long(1L), tr1.getId());
}
But, in this case:
#Test
public void testFindById() throws Exception {
ConversionService conversionService = (ConversionService) context.getBean("conversionService");
assertTrue(conversionService.canConvert(String.class, DateTime.class));
Build success!
I don't understand: why?
Thank you for any help
You don't have to create your own converter or register conversion service - if Joda-Time is in project's classpath, Spring will automagically enable conversions through #DateTimeFormat annotation (<mvc:annotation-driven /> is required).
So what you need is just:
#NotNull
#DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private DateTime dateAndTime;

Spring JavaMailSenderImpl throws an TypeMismatchException

I configured JavaMail with Spring framework using JavaMailSenderImpl in my application.Actually I tried to load mailing properties from database and done little bit changes at spring config.xml file.
But i got error
"Initialization of bean failed; nested exception is
org.springframework.beans.TypeMismatchException: Failed to convert
property value of type [com.core.springexamples.UCMSMailImpl] to
required type [org.springframework.mail.MailSender] for property
'mailSender'; nested exception is java.lang.IllegalArgumentException:
Cannot convert value of type [com.core.springexamples.UCMSMailImpl] to
required type [org.springframework.mail.MailSender] for property
'mailSender': no matching editors or conversion strategy found"
whatever changes are implemented in my application,those are mentioned in below.
Step 1:
<bean id="javaMailImpl" class="org.springframework.mail.javamail.JavaMailSenderImpl"></bean>
Step 2:-
<bean id="mailSender" class="com.core.springexamples.UCMSMailImpl" scope="prototype" init-method="configuredProperties">
<property name="javaMailImpl" ref="javaMailImpl"></property>
</bean>
com.core.springexamples.UCMSMailImpl:-
public class UCMSMailImpl {
private JavaMailSenderImpl javaMailImpl;
private ConfigDAO configDAO;
public void configuredProperties(){
System.out.println("UCMSMailImpl::configuredProperties");
Properties props=new Properties();
String[] mildata=configDAO.getMailingPropData();
props.put("mail.smtp.auth", mildata[0]);
props.put("mail.smtp.starttls.enable", mildata[2]);
props.put("mail.smtp.host", mildata[3]);
props.put("mail.smtp.port", mildata[4]);
props.put("mail.smtp.host", mildata[5]);
props.put("username", mildata[6]);
props.put("password",mildata[7]);
getJavaMailImpl().setJavaMailProperties(props);
}
public JavaMailSenderImpl getJavaMailImpl() {
return javaMailImpl;
}
public void setJavaMailImpl(JavaMailSenderImpl javaMailImpl) {
this.javaMailImpl = javaMailImpl;
}
public void setConfigDAO(ConfigDAO configDAO){
this.configDAO=configDAO;
}
public ConfigDAO getConfigDAO(){
return configDAO;
}
Step 3:-I am trying send the mail from MailSender.send using UCMSMailImpl java class.I refered the UCMSMailImpl bean.
<bean id="sendMail" class="com.core.springexamples.JavaMailing">
<property name="mailSender" ref="mailSender"></property>
</bean>
public class JavaMailing {
private MailSender mailSender;
public void sendMail(String from,String to,String text,String subject){
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
/**
* #return the mailSender
*/
public MailSender getMailSender() {
return mailSender;
}
/**
* #param mailSender the mailSender to set
*/
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
Step 4:- I trying to test the sendMail bean
ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext-mail.xml");
JavaMailing m=(JavaMailing)context.getBean("sendMail");
m.sendMail("john.ch#gmail.com", "john.c#gmail.com", "TEST MAIL", "TEST MAIL");
But i got exception is TypeMismatchException: Failed to convert property value of type [com.core.springexamples.UCMSMailImpl] to required type [org.springframework.mail.MailSender] for property
Please help me.
You cannot assign a class to an interface, if it doesn't implement the interface. UCMSMailImpl does not implement MailSender. Keep the rest as it is and change your UCMSMailImpl like this:
public class UCMSMailImpl implements MailSender {
private JavaMailSenderImpl javaMailImpl;
private ConfigDAO configDAO;
// do your property initialization
// ...
// implement interface methods
void send(SimpleMailMessage simpleMessage) throws MailException {
this.javaMailImpl.send(simpleMessage);
}
void send(SimpleMailMessage[] simpleMessages) throws MailException {
this.javaMailImpl.send(simpleMEssages);
}
}
If you cannot change UCMSMailImpl, extend it:
public class MyUCMSMailImpl extends UCMSMailImpl implements MailSender {
void send(SimpleMailMessage simpleMessage) throws MailException {
this.getgetJavaMailImpl().send(simpleMessage);
}
void send(SimpleMailMessage[] simpleMessages) throws MailException {
this.getgetJavaMailImpl().send(simpleMEssages);
}
}
and change your configuration:
<bean id="mailSender" class="your.package.MyUCMSMailImpl" scope="prototype" init-method="configuredProperties">
<property name="javaMailImpl" ref="javaMailImpl"></property>
</bean>

Resources