Spring doesn't use my Conerverter. Why? - spring

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;

Related

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

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}')}")

Bad Request : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to bind request element

First Entity:
#Entity
#Table(name = "PIL_P_DOMAINE")
public class PIL_P_DOMAINE {
#NotBlank
#Column(nullable = false, unique = true, name = "DOMAINE_ID")
private String DOMAINE_ID;
#NotBlank
#Column(nullable = false, name = "DOMAINE_DS")
private String DOMAINE_DS;
public PIL_P_DOMAINE() {
}
}
Second Entity:
#Entity
public class PIL_P_DOMAINE_TABLE {
#NotBlank
#JoinColumn(nullable = false, name = "DOMAINE_ID")
#ManyToOne
private PIL_P_DOMAINE DOMAINE_ID;
#NotBlank
#Column(nullable = false, name = "DATABASE_NM")
private String DATABASE_NM;
#NotBlank
#Column(nullable = false, name = "TABLE_NM")
private String TABLE_NM;
#Column(name = "APPLCTN_COLNM_NM")
private String APPLCTN_COLNM_NM;
#Column(name = "CRITERE_FILTRE_NM")
private String CRITERE_FILTRE_NM;
public PIL_P_DOMAINE_TABLE() {
}
}
Converter:
#Component("domaineToDomTabConverter")
public class DomaineToDomTabConverter implements Converter<Object, PIL_P_DOMAINE> {
static final Logger logger = LoggerFactory.getLogger(DomaineToDomTabConverter.class);
#Autowired
#Qualifier("pIL_P_DOMAINE_SERVICE")
IService<PIL_P_DOMAINE> domService;
/**
*
*
* #see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
public PIL_P_DOMAINE convert(Object element) {
Integer id = Integer.parseInt((String) element);
PIL_P_DOMAINE dom = domService.findById(id);
logger.info("Domaine : {}", dom);
return dom;
}
}
AppConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.fussa.fyby")
public class AppConfig extends WebMvcConfigurerAdapter {
#Autowired
DomaineToDomTabConverter domaineToDomTabConverter;
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(domaineToDomTabConverter);
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
when i try to persist an PIL_P_DOMAINE object whitout adding
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(domaineToDomTabConverter);
}
to my AppConfig class , to object is persisted (y).
The issue i have is when i want to persist an PIL_P_DOMAINE_TABLE object which contain an object PIL_P_DOMAINE, i added DomaineToDomTabConverter to convert to string i will get in form to the object so i added the converter in my AppCongig class,with those modifications i cant persist an PIL_P_DOMAINE object, i got this error:
WARN :
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
- Failed to bind request element: org.springframework.beans.TypeMismatchException: Failed to convert
value of type [com.fussa.fyby.model.PIL_P_DOMAINE] to required type
[com.fussa.fyby.model.PIL_P_DOMAINE]; nested exception is
org.springframework. core.convert.ConversionFailedException: Failed to
convert from type [com.fussa.fyby.model.PIL_P_DOMAINE] to type
[#javax.validation.Valid #org.springframework.web.bi
nd.annotation.ModelAttribute com.fussa.fyby.model.PIL_P_DOMAINE] for
value 'com.fussa.fyby.model.PIL_P_DOMAINE#716898c0'; nested exception
is java.lang.ClassCastExce ption: com.fussa.fyby.model.PIL_P_DOMAINE
cannot be cast to java.lang.String
How can i call the converter only if i want to persist my second entity and not the first ?
Thanks for any advices..
This issue was fixed by Parameterizing the type i'm converting from to String instead of Object
#Component("domaineToDomTabConverter")
public class DomaineToDomTabConverter implements Converter<String, PIL_P_DOMAINE> {
public PIL_P_DOMAINE convert(Stringelement) {
//
}
}

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?

How to inject bean in a Tapestry service

I want to inject bean in a Tapestry service (not in a page).
For the moment, I use this :
public class EntityRealm extends AuthorizingRealm {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/application-context-security.xml");
SecurityServices securityServices = (SecurityServices)ctx.getBean("securityServices");
It works, but I want use this :
public class EntityRealm extends AuthorizingRealm {
#Inject
private SecurityServices securityServices;
And my applicationContext is in the web.xml.
In this second case, the injection doesn't work. Why ?
AppModule.java :
public class AppModule
{
//#Resource(name = "realm")
#Inject
private static EntityRealm realm;
#Contribute(WebSecurityManager.class)
public static void addRealms(Configuration<EntityRealm> configuration) {
//EntityRealm realm = new EntityRealm();
configuration.add(realm);
}
public static void contributeFactoryDefaults( MappedConfiguration<String, Object> configuration)
{
configuration.override(SecuritySymbols.LOGIN_URL, "/login");
configuration.override(SecuritySymbols.UNAUTHORIZED_URL, "/login");
configuration.override(SecuritySymbols.SUCCESS_URL, "/index");
configuration.override(SymbolConstants.APPLICATION_VERSION, "2.0-SNAPSHOT");
}
public static void contributeApplicationDefaults(MappedConfiguration<String, Object> configuration)
{
configuration.add(SymbolConstants.HMAC_PASSPHRASE, new BigInteger(130, new SecureRandom()).toString(32));
configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en,fr");
configuration.add( "tapestry.default-cookie-max-age", "31536000" );
}
public RequestFilter buildTimingFilter(final Logger log)
{
return new RequestFilter()
{
public boolean service(Request request, Response response, RequestHandler handler)
throws IOException
{
long startTime = System.currentTimeMillis();
try
{
return handler.service(request, response);
} finally
{
long elapsed = System.currentTimeMillis() - startTime;
log.info(String.format("Request time: %d ms", elapsed));
}
}
};
}
public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
#Local
RequestFilter filter)
{
configuration.add("Timing", filter);
}
}
And the EntityRealm.java :
public class EntityRealm extends AuthorizingRealm {
//***************************************
//************* Attributes *************
//***************************************
//ApplicationContext ctx = new ClassPathXmlApplicationContext("/application-context-security.xml");
//SecurityServices securityServices = (SecurityServices)ctx.getBean("securityServices");
//#Resource(name = "securityServices")
#Inject
private SecurityServices securityServices;
//***************************************
//************ Constructors *************
//***************************************
public EntityRealm() {
super(new MemoryConstrainedCacheManager());
setName("myapprealm");
setAuthenticationTokenClass(UsernamePasswordToken.class);
}
//***************************************
//********** Public Methods *************
//***************************************
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) throw new AuthorizationException("PrincipalCollection was null, which should not happen");
application-context.xml :
<bean id="realm" class="net.atos.m2m.telecom.ihm.services.EntityRealm">
<property name="securityServices" ref="securityServices"></property>
</bean>
<bean id="securityServices" class="net.atos.m2m.telecom.ihm.applicatif.services.security.impl.SecurityServicesImpl">
<property name="servicesTelSecu" ref="servicesTelSecu"></property>
<property name="converterSecDSPtoDTO" ref="converterSecDSPtoDTO"></property>
<property name="converterSecDTOtoDSP" ref="converterSecDTOtoDSP"></property>
</bean>
Can you help me ?
Thank you.
How i say in previous comment, if you create EntityRealm in this way .. new EntityRealm() the inject\autowire does not work.
You must define EntityRealm as bean .. XML or Annotation.
<bean id="entityRealm" class="package.EntityRealm"/>
<bean id="securityServices" class="package.SecurityServices"/>
You can use #Resource instead,
#Resource(name = "securityServices")
private SecurityServices securityServices;
And make sure that application-context-security.xml file is loaded by Spring.

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