Today I'm working on a project in Java Spring, especially in CONTEXT-SERVLET.xml (context) where normally declare a bean to link a .jsp with a Java class or controller (mapping).
Traditional workflow is: a viewA.jsp is linked (mapping) to controller.java (controller) and this controller.java dispatches another viewB.jsp.
Can you link a viewA.jsp to another viewB.Jsp without going through a controller?
How do this in CONTEXT-SERVLET.xml?
You can use ParameterizableViewController to redirect a request to jsp file without visiting controller.
For example
1. Mapping /welcome.htm to welcomeController
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.htm">welcomeController</prop>
</props>
</property>
</bean>
2. Mapping viewName property of welcomeController to WelcomePage
<bean name="welcomeController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName" value="WelcomePage" />
</bean>
3. Defining view resolver
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
It will map /welcome.htm to /WEB-INF/pages/welcomePage.jsp.
Source for more details.
< mvc:view-controller path="/" view-name="home" />
This is a shortcut for defining a ParameterizableViewController that immediately forwards to a view when invoked. Use it in static cases when there is no Java controller logic to execute before the view generates the response.
see link http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-view-controller
Related
I want to change a property of a bean. I want to change it only once for performance (better when reading from XML), not in every bean instance instantiation. What is the best way to do it in Spring?
For elaborating and giving a concrete example:
Below is the datasource bean declaration in databaseContext.xml.
I want to decrypt ${jdbc.password} whose value is ENC(....) with JASYPT.
I could not do it with Jaspt Spring integration since Jaspt not compliant yet with Spring5 and not with Jasypt Hibernate integration since using a different datasource other than Hibernate.
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP" />
<property name="connectionTestQuery" value="SELECT 1 from dual" />
<property name="dataSourceClassName" value="oracle.jdbc.pool.OracleDataSource" />
<property name="maximumPoolSize" value="10" />
<property name="idleTimeout" value="30000" />
<property name="dataSourceProperties">
<props>
<prop key="url">${jdbc.url}</prop>
<prop key="user">${jdbc.user}</prop>
<prop key="password">${jdbc.password}</prop>
</props>
</property>
</bean>
This helped me a lot:
Spring property placeholder decrypt resolved property
Just want to add some small correction and extra notes about some findings:
In the link above it is written "location", but it must be "locations" as written below, where it resides at applicationContext.xml
<bean class="com.dummy.util.EncryptationAwarePropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:database.properties</value>
<value>classpath*:hibernate.properties</value>
</list>
</property>
</bean>
"PropertyPlaceholderConfigurer" is deprecated. But it still works. If you try to use the newly proposed class "PropertySourcesPlaceholderConfigurer", it has a bug that it does not call "convertPropertyValue" method as noted here: https://github.com/spring-projects/spring-framework/issues/13568. A workaround noted by the way there.
public class EncryptationAwarePropertySourcesPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
#Override
protected String convertPropertyValue(String originalValue) {
if (originalValue != null && originalValue.startsWith("ENC(")) {
return decrypt(originalValue);
}
return originalValue;
}
.
.
}
I encouter an issue "Spring transaction fail rollback". I have a service class which call 2 DAO to insert data into DB table.
emTrcvLineDAO.create(lineVo) fail to insert into table as the lineVo missing some mandatory fields, but emTrcvHeaderDAO.create(vo) fail rollback and the data still inserted in to DB successfully. I am wondering why it does not rollback as the two DAO are in the same transaction.
Any guys have idea on this? Thanks in advance.
public void saveEmTrcvHeader(List<EmTrcvHeaderVOImpl> voList, List<ResponseItem> responseItemList) {
for (EmTrcvHeaderVOImpl vo : voList) {
emTrcvHeaderDAO.create(vo);
List<EmTrcvLineVOImpl> lineList = vo.getLineList();
for (int i = 0; i < lineList.size(); i++) {
EmTrcvLineVOImpl lineVo = lineList.get(i);
lineVo.setEmTrcvHeaderId(vo.getEmTrcvHeaderId());
lineVo.setProjId(null);
emTrcvLineDAO.create(lineVo);
}
}
}
My transaction configuration:
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED,-java.lang.Exception,-org.springframework.dao.DataAccessException</prop>
<prop key="*">PROPAGATION_REQUIRED,-java.lang.Exception,-org.springframework.dao.DataAccessException</prop>
</props>
</property>
</bean>
My service and dao defined as below:
<bean name="emTrcvHeaderService" parent="txProxyTemplate">
<property name="target">
<bean class="com.emtrcv.service.EmTrcvHeaderService">
<property name="emTrcvHeaderDAO">
<ref bean="emTrcvHeaderDAO"/>
</property>
<property name="emTrcvPubSelectIdsDAO">
<ref bean="emTrcvPubSelectIdsDAO"/>
</property>
<property name="emTrcvLineDAO">
<ref bean="emTrcvLineDAO"/>
</property>
</bean>
</property>
</bean>
<bean name="emTrcvHeaderDAO" class="com.emtrcv.dao.EmTrcvHeaderDAOImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean name="emTrcvPubSelectIdsDAO" class="com.emtrcv.dao.EmTrcvPubSelectIdsDAOImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean name="emTrcvLineDAO" class="com.emtrcv.dao.EmTrcvLineDAOImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
I think you have to mention when rollback should take place.
As per doc,
The concept of rollback rules is important: they enable you to specify which exceptions (and throwables) should cause automatic rollback. You specify this declaratively, in configuration, not in Java code. So, although you can still call setRollbackOnly() on the TransactionStatus object to roll back the current transaction back, most often you can specify a rule that MyApplicationException must always result in rollback.
Please refer http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html for more details
Finally I found the root cause. there are two duplicate Spring configuration files both define transaction management rules in the project, it make spring tranasction management not work. After removed one of them, it works.
Can't get bean from spring container in listener or filter classes.
Have you used something like this :
#Autowired
private ApplicationContext context;
ICustomer customer = (ICustomer) context.getBean("name"); // here name is the name of the bean you want to get context
look I have used this in my project like this ans works well :
String processorName = Introspector.decapitalize(command.getClass().getSimpleName() + "Processor");
ICommandProcessor processor = (ICommandProcessor) context.getBean(processorName);
here if I ll pass command Add then it ll pass processorName = AddProcessor and get it's context.
what is your requirement ? can you post code ?
Look this xml file then check yours from it :
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="com.domain"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
here : <property name="packagesToScan" value="com.domain"/> is important when you want to use #Autowired in my project it's com.domain, so refer this and make changes as you need. then again post.
I'm using Spring MVC for a web app project and I'm trying to avoid using annotations.
I came across as far as getting MultiActionController and delegate working.
The question is, how do I set the default method in the delegate of a MultiActionController ?
By MultiActionController, I mean something like this
public class TestController1 extends MultiActionController{
public TestController1(){
System.out.println("TestController1 initialising...");
}
}
My xml settings are...
<bean id="multiactionController1" class="test.TestController1">
<property name="delegate" ref="testDelegater1"/>
<property name="methodNameResolver" ref="paramResolver"/>
</bean>
<!-- Delegaters -->
<bean id="testDelegater1" class="test.TestController1Delegator"/>
<!-- param method name resolver -->
<bean id="paramResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName" value="action"/>
</bean>
<!-- Simple Url Handler Mapping -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<map>
<entry key="/multiaction1/**" value-ref="multiactionController1"/>
<entry key="/item/**" value-ref="itemController"/>
</map>
</property>
</bean>
So when I send a request like '*/item' , notice it doesn't have an action parameter, instead of giving me an error I would like to have a default method.
Use following implementation of MethodNameResolver, it has defaultMethodName property.
org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver
I was able to solve this by following instructions in this page.
http://www.cwinters.com/blog/2004/02/18/spring_setting_a_default_action_for_multiactioncontroller.html
As far as I've figured, you need to implement your own MethodNameResolver that returns default method name if no method name has been specified.
I Hope this helps : )
I have a string property which looks similar to the following example:
<property name="mappingData">
<list>
<bean class="com.company.product.longNamingStandard.migration.extractor.FieldMapping">
<property name="elementName" value="entitlement.user"/>
<property name="mapping" value="DocUsers"/>
</bean>
<bean class="com.company.product.longNamingStandard.migration.extractor.FieldMapping">
<property name="elementName" value="entitlement.contributor"/>
<property name="mapping" value="DocContributors"/>
</bean>
</list>
</property>
The long class name(s) effect readability & also create a refactoring overhead.
Is it possible to alias the class name and use a short name to declare the beans? Or is there an alternate best practice I'm missing?
Probably a bit late for you, but hopefully useful for others:
You can use parent beans to accomplish this.
First declare a parent bean as a template:
<bean id="FieldMapping" class="com.company.product.longNamingStandard.migration.extractor.FieldMapping"/>
Then use it elsewhere, using the parent attribute.
<property name="mappingData">
<list>
<bean parent="FieldMapping">
<property name="elementName" value="entitlement.user"/>
<property name="mapping" value="DocUsers"/>
</bean>
<bean parent="FieldMapping">
<property name="elementName" value="entitlement.contributor"/>
<property name="mapping" value="DocContributors"/>
</bean>
</list>
</property>
Please note my convention here is to use upper case id's here for the parent template beans.
each <bean/> comes with an attribute of name and id to help you reference those beans later in your configuration.
I would suggest using the id for declaring the bean.
your config could look like:
<bean id="fooBean" class="com.example.foo"/>
<bean id="barBean" class="com.example.bar"/>
<list>
<ref>fooBean</ref>
<ref>barBean</ref>
</list>
You may try to represent your mapping in some short form, and then convert it to the list of FieldMappings. For example, mappings from your snippet may be represented as a map.
As a theoretic exercise in Spring 3 you can do this with Spring Expression Language (if FieldMapping has the apropriate constructor):
<util:map id = "m">
<entry name = "entitlement.user" value = "DocUsers" />
<entry name = "entitlement.contributor" value = "DocContributors" />
</util:map>
...
<property name = "mappingData"
value = "#{m.![new com.company.product.longNamingStandard.migration.extractor.FieldMapping(key, value)]}" />
If this expression is too obscure, you may implement a FactoryBean to take a short form of your mapping data (for example, a map, as in this example) and return a configured list of FieldMappings:
<property name = "mappingData">
<bean class = "FieldMappingListFactoryBean">
<property name = "mappings">
<map>
<entry name = "entitlement.user" value = "DocUsers" />
<entry name = "entitlement.contributor" value = "DocContributors" />
</map>
</property>
</bean>
</property>
However, if your field mappings are some kind of reusable DSL, you may try to think about implementing a namespace extension.
I found a way to simulate an effect similar to a "import com.Foo;" in java code. The best option I could find was to use a PropertyPlaceholderConfigurer with local properties defined. Using your example, here's the configuration that you would put at the top of your spring config file to define a "class_FieldMapping" property:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<description>Define properties equivalent to "import foo;" in java source</description>
<property name="properties">
<props>
<prop key="class_FieldMapping">com.company.product.longNamingStandard.migration.extractor.FieldMapping</prop>
</props>
</property>
</bean>
Then, you can use that property within your beans:
<property name="mappingData">
<list>
<bean class="${class_FieldMapping}">
...
</bean>
<bean class="${class_FieldMapping}">
...
</bean>
</list>
</property>
This has the benefit that use can also use it for things where you actually need the class name, and can't reference an instance of an object:
<util:constant static-field="${class_FieldMapping}.MYSTATICVAR" />
Why not declare those inner beans as separate top-level beans with their own names, and then reference them in the list ?
If I use PropertyPlaceholderConfigurer it leads to several exceptions in debug log. It works, but it seems it doesn't work on the first try.