How can I create bean for adviceChain? - spring

I'm having a hard time converting this spring xml into java config. How can I define an adviceChain bean base on the below spring file.
This's my xml file:
<util:list id="adviceChain">
<ref bean="retryInterceptor"/>
</util:list>
<bean id="retryInterceptor" class="org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean">
<property name="messageRecoverer">
<bean class="customDiscardingMessageRecoverer" />
</property>
<property name="retryOperations" ref="retryTemplate" />
</bean>
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.FixedBackOffPolicy">
<property name="backOffPeriod" value="3000" />
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="3" />
</bean>
</property>
</bean>
Here is what I tried:
#Bean
StatelessRetryOperationsInterceptorFactoryBean retryInterceptor() {
StatelessRetryOperationsInterceptorFactoryBean retryInterceptor = new StatelessRetryOperationsInterceptorFactoryBean();
DiscardingMessageRecoverer messageRecoverer = new DiscardingMessageRecoverer();
retryInterceptor.setMessageRecoverer(messageRecoverer);
retryInterceptor.setRetryOperations(retryTemplate());
return retryInterceptor;
}
#Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(3000);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
#Bean
SimpleMessageListenerContainer listenerContainer(){
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setConcurrentConsumers(1);
listenerContainer.setAdviceChain(new Advice[] { (Advice) retryInterceptor() });
listenerContainer.setMessageListener(listenerAdapter());
listenerContainer.setQueues(queue());
return listenerContainer;
}
I receive org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean$$EnhancerBySpringCGLIB$$e3de830c cannot be cast to org.aopalliance.aop.Advice error at the line listenerContainer.setAdviceChain(new Advice[] { (Advice) retryInterceptor() });
I think this's because I didn't define AdviceChain bean like the spring xml file but so far I don't know how.

Edit StatelessRetryOperationsInterceptorFactoryBean like this :
#Bean
RetryOperationsInterceptor retryInterceptor() {
StatelessRetryOperationsInterceptorFactoryBean retryInterceptor = new StatelessRetryOperationsInterceptorFactoryBean();
DiscardingMessageRecoverer messageRecoverer = new DiscardingMessageRecoverer();
retryInterceptor.setMessageRecoverer(messageRecoverer);
retryInterceptor.setRetryOperations(retryTemplate());
return retryInterceptor.getObject();
}

Related

Spring property Injection using annotations

I want to configure below type of bean initialization to be performed by annotation.
Below is sample bean configuration in xml type and want to configure this kind of bean using annotations.
<bean id="Animal" class="aaa.type.Animal">
<property name="Animal" value="${Animal}" />
<property name="AnimalFamily" >
<bean class="aaa.type.AnimalFamily">
<property name="AnimalCharactertitic">
<list>
<bean class="aaa.type.AnimalColor">
<property name="name" value="Color" />
<property name="value" value="${color}" />
</bean>
<bean class="aaa.type.AnimalType">
<property name="name" value="Animal Type" />
<property name="value" value="${AnimalType}" />
</bean>
</list>
</property>
</bean>
</property>
</bean>
You can do something like this:
#Configuration
public class MyConfigurationClass {
#Bean
public AnimalCharactertitic animalColor(#Value("${color}") String color) {
AnimalCharactertitic animalCharactertitic = new AnimalCharactertitic();
animalCharactertitic.setName("Color");
animalCharactertitic.setValue(color);
return animalCharactertitic;
}
#Bean
public AnimalCharactertitic animalType(#Value("${AnimalType}") String animalType) {
AnimalCharactertitic animalCharactertitic = new AnimalCharactertitic();
animalCharactertitic.setName("Animal Type");
animalCharactertitic.setValue(animalType);
return animalCharactertitic;
}
#Bean
public AnimalFamily animalFamily(#Autowired AnimalCharactertitic animalColor,
#Autowired AnimalCharactertitic animalType) {
AnimalFamily animalFamily = new AnimalFamily();
List<AnimalCharactertitic> animalCharactertitics = new ArrayList<>();
animalCharactertitics.add(animalColor);
animalCharactertitics.add(animalType);
animalFamily.setAnimalCharactertitic(animalCharactertitics);
return animalFamily;
}
#Bean
public Animal animal(#Value("${Animal}") String animal, #Autowired AnimalFamily animalFamily) {
Animal animal = new Animal();
animal.setAnimal(animal);
animal.setAnimalFamily(animalFamily);
return animal;
}
}

render multiple suffixes with one template engine in spring-boot

I created two thymleaf resolvers and added them to a template engine, so I can process txt/svg templates in spring-boot.
#Configuration
public class TemplateEngineConfig {
#Bean
public SpringTemplateEngine textTemplateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(textTemplateResolver());
templateEngine.addTemplateResolver(svgTemplateResolver());
return templateEngine;
}
private ITemplateResolver textTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setOrder(1);
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".txt");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCacheable(false);
return templateResolver;
}
private ITemplateResolver svgTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setOrder(2);
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".svg");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCacheable(false);
return templateResolver;
}
}
I use it like this.
#Component
public class TemplateRenderer {
#Autowired
#Qualifier("textTemplateEngine")
private TemplateEngine textTemplateEngine;
public String renderPlainText(String filename, Map<String, Object> params) {
Context context = new Context(LocaleContextHolder.getLocale(), params);
return textTemplateEngine.process(filename, context);
}
}
It didn't work. I tried to render templates/img.svg, but Thymleaf complained that it couldn't find templates/img.txt file, how can I make it work?
Just force your SpringTemplateEngine to check for the existence of the templates and not only use the defined patterns. Please force that by adding
templateResolver.setCheckExistence(true);
to each of your template resolvers.
I think you should marked ITemplateResolver with #bean and Qualifier so when
you will #autowire textTemplateEngine or svgTemplateEngine so spring will autowire them with Qualifier name.
#Bean
#Qualifier("textTemplateEngine")
private ITemplateResolver textTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setOrder(1);
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".txt");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCacheable(false);
return templateResolver;
}
#Bean
#Qualifier("svgTemplateEngine")
private ITemplateResolver svgTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setOrder(2);
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".svg");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCacheable(false);
return templateResolver;
}
Also you can configure Thymeleaf multiple resolvers by xml config like:
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8" />
<property name="templateEngine">
<bean class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="dialects">
<set>
<bean class="org.thymeleaf.spring4.dialect.SpringStandardDialect" />
</set>
</property>
<property name="templateResolvers">
<set>
<bean class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="cacheable" value="false" />
<property name="prefix" value="/fragments/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
<bean class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="cacheable" value="false" />
<property name="prefix" value="/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
</set>
</property>
</bean>
</property>
</bean>

Spring boot - 2 JNDI configuration

Posted my current configuration
#Configuration
public class Config {
#Value("${spring.datasource.primary.jndi-name}")
private String primaryJndiName;
#Value("${spring.datasource.secondary.jndi-name}")
private String secondaryJndiName;
#Primary
#Bean(destroyMethod = "") // destroy method is disabled for Weblogic update app ability
public DataSource primaryDs() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(primaryJndiName);
}
#Bean(destroyMethod = "") // destroy method is disabled for Weblogic update app ability
public DataSource secondaryDs() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(secondaryJndiName);
}
}
I implemented this way and it is working
you can put your jndi values in one properties file and then load that property file in your bean defination.xml
jndi.properties
#JNDI property for job repository
job.repository.db.connection=jdbc/pgDB
#JNDI property for application
application.db.connection=jdbc/db2Conn
Bean-defination.xml
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:/properties/jndi.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
<bean id="jobRepoDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${job.repository.db.connection}" />
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${application.db.connection}" />
</bean>

No transactional EntityManager available Error

I have a below spring setup. Basically I am trying to configure two transaction managers here. One with hibernate and other with JPA. But somehow when I try to run JPA transaction manager, there I get "javax.persistence.TransactionRequiredException: No transactional EntityManager available" error. Appreciate if somebody finds the problem in below code.
data-context.xml file as below
<bean id="fundBO" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.test.FundBo"/>
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
<idref bean="fundBOTarget"/>
</list>
</property>
</bean>
<bean id="fundBOTarget" class="com.test.FundBoImpl" />
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<bean class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
</bean>
And AppConfig as Below.
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan(basePackages = {"com.test.**"})
#ImportResource("classpath:data-context.xml")
public class AppConfig {
#Resource
DataSource dataSource;
#Bean
public JpaTransactionManager jpaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
transactionManager.setJpaDialect(new HibernateJpaDialect());
transactionManager.setNestedTransactionAllowed(true);
transactionManager.afterPropertiesSet();
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPersistenceProviderClass(HibernatePersistence.class);
factoryBean.setPackagesToScan("com.test.**");
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
jpaProperties.put("hibernate.jdbc.batch_size", "20");
jpaProperties.put("hibernate.show_sql", "false");
jpaProperties.put("hibernate.hbm2ddl.auto", "validate");
jpaProperties.put("hibernate.autoReconnect", "true");
jpaProperties.put("hibernate.autoReconnectForPools", "true");
jpaProperties.put("hibernate.is-connection-validation-required", "true");
factoryBean.setJpaProperties(jpaProperties);
factoryBean.afterPropertiesSet();
return factoryBean;
}
}

Spring Batch- Xml based configuration performance over Java based

I am trying to convert the spring batch configuration from xml based to annotation based.
Below is my xml based configuration.
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<!-- Step will need a transaction manager -->
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="dbMapper" class="org.test.DBValueMapper">
</bean>
<bean id="dbMapperFlatfile" class="org.test.FlatFileRowMapper">
</bean>
<bean id="paramSetter" class="org.test.DBParamSetter">
</bean>
<bean id="dbReader" class="org.test.DBValueReader"
scope="step">
<property name="paramSetter" ref="paramSetter"/>
<property name="verifyCursorPosition" value="false" />
<property name="dataSource" ref="dataSource" />
<property name="sql" value="#{jobParameters['SQL_QUERY']}" />
<property name="rowMapper" ref="dbMapper" />
<property name="fetchSize" value="5000" />
</bean>
<bean id="dbWriterIO" class="org.test.TemplateWritterIO"
scope="step">
<property name="velocityEngine" ref="velocityEngine" />
<!-- <property name="rptConfig" value="#{jobParameters['RPT_CONFIGVAL']}" /> -->
<property name="headerCallback" ref="dbWriterIO" />
<property name="footerCallback" ref="dbWriterIO" />
</bean>
<batch:job id="fileGenJobNio">
<batch:step id="fileGenJobStempNio">
<batch:tasklet>
<batch:chunk reader="dbReader" writer="dbWriterNIO"
commit-interval="5000">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
Below is the equivalent Java based configuration:
#EnableBatchProcessing
#Import({ServiceConfiguration.class})
public class SRBatchGenerator extends DefaultBatchConfigurer{
#Autowired
private JobBuilderFactory jobBuilders;
#Autowired
private StepBuilderFactory stepBuilders;
#Autowired
private VelocityEngine velocityEngine;
#Autowired
private DBValueMapper mapper;
#Autowired
private DbHelper dbhelper;
#Autowired
private DataSource datasource;
#Bean
public Step step(){
return stepBuilders.get("step")
.chunk(5000)
.reader(reader())
//.processor(processor())
.writer(writer())
//.listener(logProcessListener())
.faultTolerant()
//.skipLimit(10)
//.skip(UnknownGenderException.class)
//.listener(logSkipListener())
.build();
}
#Bean
public Job fileGeneratorJob(){
return jobBuilders.get("fileGeneratorJob")
//.listener(protocolListener())
.start(step())
.build();
}
#Bean
public DBValueMapper mapper(){
return new DBValueMapper();
}
#Bean
#StepScope
public DBValueReader3 reader(){
String query="Select Test1,Test2,test3,test4 from RPt_TEST";
DBValueReader3 dbread = new DBValueReader3();
dbread.setSql(query);
dbread.setRowMapper(mapper);
dbread.setDataSource(datasource);
return dbread;
}
#Bean
#StepScope
public TemplateWritterIO writer(){
TemplateWritterIO writer=new TemplateWritterIO();
writer.setVelocityEngine(velocityEngine);
return writer;
}
#Override
protected JobRepository createJobRepository() throws Exception {
MapJobRepositoryFactoryBean factory =
new MapJobRepositoryFactoryBean();
factory.afterPropertiesSet();
return (JobRepository) factory.getObject();
}
}
When I execute my Job using xml based it took 27sec to write 1 Million record into Flat file.
But to write same 1 million record, Java based job took about 2 hours to write.
I am not sure what I am missing here. Can anyone help me or guide me why it is slow in Java based configuration.

Resources