how can i change this xml configuration :
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
...
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
</set>
</property>
...
</bean>
to a java code configuration so far i have this i only have problems in this part :
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
</set>
</property>
this is what i have so far in java code :
#Bean
public SpringSecurityDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver( templateResolver() );
engine.setMessageSource( messageSource() );
//DIALECTS
Set<SpringSecurityDialect> ssdSet = new HashSet<SpringSecurityDialect>();
ssdSet.add( springSecurityDialect() );
engine.setAdditionalDialects( ssdSet ); <-- this line give me this error
return engine;
}
this line give me this error: The method setAdditionalDialects(Set<IDialect>) in the type TemplateEngine is not applicable for the arguments (Set<SpringSecurityDialect>)
I banged my head against this for a while today. The answer lay in looking at the Spring Boot source:
https://github.com/spring-projects/spring-boot/blob/v1.2.5.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration.java
#Configuration
#ConditionalOnClass({ SpringSecurityDialect.class })
protected static class ThymeleafSecurityDialectConfiguration {
#Bean
#ConditionalOnMissingBean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
}
So Spring Boot (well, "org.springframework.boot:spring-boot-starter-thymeleaf") will try to inject the org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect. Perhaps it's not working because I have the springsecurity4 jar.
In any case, there's a simple fix: just do what Spring Boot tries to do. In an #Configuration class, just add the bean:
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
According to your config, property additionalDialects should assigned with a Set containing one bean. So in javaconfig just create an instance of HashSet, add to it SpringSecurityDialect bean and assign the resulting set to additionalDialects property.
SpringSecurityDialect bean should be created by method annotated with #Bean to let Spring application context know about this bean to execute bean initializers and postprocessors.
Following code illustrates it:
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver( templateResolver() );
engine.setMessageSource( messageSource() );
Set<SpringSecurityDialect> ssdSet = new HashSet<SpringSecurityDialect>();
ssdSet.add( springSecurityDialect() );
engine.setAdditionalDialects( ssdSet );
return engine;
}
#Bean
public SpringSecurityDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
You could instantiate the entire engine using code similar to this.
FileSystemXmlApplicationContext appCtx = new FileSystemXmlApplicationContext("myconfigfile.xml");
if (appCtx.containsBean("templateEngine") {
SpringTemplateEngine engine = (SpringTemplateEngine) appCtx.getBean("templateEngine");
}
The additional dialects and any other properties you've set on the engine in your xml configuration file will be applied.
You might want to look at using ClassPathXmlApplicationContext instead of the FileSystem one in my example.
Related
I am new to Spring, I am working in moving some bean definitions from XML to #Configuration Class.
Here is one of the beans I am struggling with:
<bean id="jmsProducerTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="connectionFactory"/>
<jms:listener-container container-type="default"
connection-factory="connectionFactory"
acknowledge="auto">
<jms:listener destination="YOURQUEUENAME" ref="theListenerClassYouAreUsing" />
</jms:listener-container>
How would that look in a #Configuration class, thanks.
So far I have this
#Bean("myContainerFactory")
public JmsListenerContainerFactory myContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
ConnectionFactory connectionFactory = pooledConnectionFactory();
factory.setConnectionFactory(connectionFactory);
factory.setPubSubDomain(false);
return factory;
}
I am missing the destination set, no idea how to do it.
You have to add a listener as well, see for example Annotation-driven Listener Endpoints:
#Component
public class MyService {
#JmsListener(destination = "YOURQUEUENAME", containerFactory = "myContainerFactory")
public void myListener(String data) { ... }
}
I have an interceptor written in XML:
<bean class ="com.packt.webstore.interceptor.AuditingInterceptor"/>
<bean class ="com.packt.webstore.interceptor.PromoCodeInterceptor" >
<property name="promoCode" value ="OF3RTA"/>
<property name="errorRedirect" value="invalidPromoCode"/>
<property name ="offerRedirect" value ="products"/>
</bean >
How do I write the same thing in Spring Boot? I tried this:
#Bean
PromoCodeInterceptor promoCodeInterceptor() {
PromoCodeInterceptor promoCodeInterceptor = new PromoCodeInterceptor();
promoCodeInterceptor.setPromoCode("OF3RTA");
promoCodeInterceptor.setErrorReidect("invalidPromoCode");
promoCodeInterceptor.setOfferRedirect("products");
return promoCodeInterceptor;
}
But it doesn't work.
///edit
And what about this one?
<bean id="productValidator"
class="com.packt.webstore.validator.ProductValidator">
<property name="springValidators">
<set>
<ref bean = "unitsInStockValidator"/>
</set >
</property>
</bean >
<bean id ="unitsInStockValidator" class
="com.packt.webstore.validator.UnitsInStockValidator"/>
This code is ok?
#Bean
public ProductValidator productValidator() {
ProductValidator productValidator = new ProductValidator();
productValidator.setSpringValidators(unitsInStockValidator());
return productValidator;
}
#Bean
public UnitsInStockValidator unitsInStockValidator() {
UnitsInStockValidator unitsInStockValidator = new UnitsInStockValidator();
return unitsInStockValidator;
}
#Bean annotations working only in classes marked with #Configuration.
Create new class and put your bean definition in it
#Configuration
public class MyConfig {
#Bean
public PromoCodeInterceptor promoCodeInterceptor() {
PromoCodeInterceptor promoCodeInterceptor = new PromoCodeInterceptor();
promoCodeInterceptor.setPromoCode("OF3RTA");
promoCodeInterceptor.setErrorReidect("invalidPromoCode");
promoCodeInterceptor.setOfferRedirect("products");
return promoCodeInterceptor;
}
}
I declared Spring Beans in my beans.xml:
<context:annotation-config />
<context:component-scan base-package="com.pack"/>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="dataSource" ref="dataSource"></property>
</bean>
dataSource and sessionFactory beans:
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUsername(userName);
ds.setPassword(password);
ds.setDriverClassName(driverName);
ds.setUrl(url);
return ds;
}
#Bean(name = "sessionFactory")
public LocalSessionFactoryBean localSessionFactoryBean() {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setDataSource(dataSourceConfiguration.dataSource());
Properties props = new Properties();
props.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
props.put("hibernate.hbm2ddl.auto", "update");
props.put("hibernate.current_session_context_class", "thread");
factory.setHibernateProperties(props);
factory.setMappingResources("com/pack/Item.hbm.xml");
return factory;
}
If I use sessionFactory and dataSource beans separately they work well. A also have DAO class:
#Repository(value = "itemDaoHibernateImpl")
public class ItemDaoHibernateImpl implements ItemDao {
#Resource(name = "sessionFactory")
private SessionFactory factory;
public void setFactory(SessionFactory factory) {
this.factory = factory;
}
public Session session() {
return factory.getCurrentSession();
}
#Override
public void create(Item item) {
session().save(item);
}
I don't open the sessions because I want to force Spring to do this. I have Service class with method:
#Override
#Transactional
public void create(Item item) {
dao.create(item);
}
When I call it, I have the exception:
org.hibernate.HibernateException: save is not valid without active transaction
I've done like this tutorial tells. Where is my mistake?
Try to remove props.put("hibernate.current_session_context_class", "thread") from your sessionFactory configuration. When you are using Spring managed transactions, you don't need it. Let me know if that works.
When I have come across this before it is due to whether Spring is using CGLib or Javassist to augment your class to provide transactionality. if I remember correctly if you only have Javassist in then the class that Spring needs to create the proxy on in order to implement the Transactional annotation must implement an interface.
Java - Spring
I have spring factory bean creation in .xml
<bean id="concurrentHashMapFactory" class="com.abc.HashMapFactory.ConcurrentHashMapFactory"/>
<bean id="idCorpMap" factory-bean="concurrentHashMapFactory" factory-method="createIdCorpMapInstance"/>
but i want to convert above .xml statement into equivalent using annotation any help ?
Roughly like this (I didn't test it)..
#Configuration
public class Config {
#Bean(name = "concurrentHashMapFactory")
public ConcurrentHashMapFactory createConcurrentHashMapFactory() {
return new ConcurrentHashMapFactory();
}
#Bean(name = "idCorpMap")
public IdCorpMapType createIdCorpMap(ConcurrentHashMapFactory factory) {
return factory.createIdCorpMapInstance();
}
}
I have the following code snippet which I use to expose a BridgePropertyPlaceholderConfigurer Bean through Annotation Configuration:
#Configuration
public class SpringConfiguration {
#Bean
public static BridgePropertyPlaceholderConfigurer getProperties() {
File conf = new File(new File(".").getAbsolutePath() + "/configuration.properties");
BridgePropertyPlaceholderConfigurer configurer;
configurer = new BridgePropertyPlaceholderConfigurer();
Resource[] resources = {
new FileSystemResource(conf.getAbsolutePath())
};
configurer.setLocations(resources);
return configurer;
}
}
So basically, I want to expose a properties file that is located in the same folder as the jar. Thats why I'm doing the crazy stuff with File
Is there anyway however which I could convert this into XML configuration?
Something like:
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location" value="#{new File('.')....}"/>
</bean>
You can create the bean using a factory:
<bean id="bridgePropertyPlaceholderConfigurerFactory"
class="foo.bar.BridgePropertyPlaceholderConfigurerFactory" />
<bean id="bridgePropertyPlaceholder"
factory-bean="bridgePropertyPlaceholderFactory"
factory-method="createBridgePropertyPlaceholderConfigurer" />
Java factory:
public class BridgePropertyPlaceholderConfigurerFactory {
public BridgePropertyPlaceholderConfigurer createBridgePropertyPlaceholderConfigurer() {
// your creation code ..
return ..
}
}
Have a look at the documentation for more details on factory methods.