Chaining spring view resolvers - spring

Is there an alternative way to achieve the next behavior in spring?:
Given path xxx/yyy
1) Look up for static/html/xxx/yyy.html
2) In case html doesn't exist look up for WEB-INF/xxx/yyy.jsp
I was trying the next config. But it seems UrlBasedViewResolver fails and doesn't delegate to the next ViewResolver.
So it seems u can't actually chain two UrlBasedViewResolver in Spring, am I right?
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
<property name="order" value="1" />
</bean>
<bean id="htmlViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/static/html/" />
<property name="suffix" value=".html" />
<property name="order" value="0" />
</bean>
Any help would be appreciated.
Cheers.

As you say, you can't, because UrlBasedViewResolver (or InternalResourceViewResolver) always resolves the view and is not possible to delegate to next ViewResolver. Reference says that this kind of ViewResolver always need to be the last.
There are some workarounds that may help you, as implementing your custom ViewResolver.

Related

Spring <util:map> shorthand as a bean property?

I've searched quite a bit but haven't found an example or statement about this.
Is it possible to use the Spring (4.3 at this point) XML <util:map> shorthand to assign a property within a bean?
Specifically, I'd like to simplify/shorten this:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="properties" value-ref="properties"/>
</map>
</property>
</bean>
Xml-wise that looks about as terse as it's going to get! The DTD doesn't support anything else.
Since you need refs, nothing inline is going to be any shorter either.
Sure.Here is an example for you :
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<util:map>
<entry key="key1" value="strValue" /> <!-- value is string -->
<entry key="key2" value="1234" value-type="java.lang.Integer" /> <!-- Use value-type to explicitly specify the type -->
<entry key="key3" value-ref="fooBean"/> <!-- Use value-ref to reference to other bean -->
</util:map>
</property>
</bean>
Shortest I've found is this, which is 2-3 lines shorter, depending on formatting. And assuming you already have the necessary namespaces defined:
<util:map id="attributes">
<entry key="properties" value-ref="properties"/>
</util:map>
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter"
p:attributes-ref="attributes"/>
But arguably not worth the additional indirection and (IMO) lower readability.

How to avoid hardcoded names in DelimitedLineTokenizer names?

I am using DelimitedLineTokenizer to read from a txt file using FlatFileItemReader. However, is there a way to avoid hardcoding the "names" property of the fields ? Instead can we use any bean ?
<bean id="employeeReader" class="org.springframework.batch.item.file.FlatFileItemReader"
scope="step">
<property name="resource" value="#{jobParameters['input.file.name']}" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="empId,empName,empAge" />
</bean>
</property>
<property name="fieldSetMapper">
<bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="targetType" value="com.example.Employee" />
</bean>
</property>
</bean>
</property>
</bean>
Currently there is not because the result of the LineTokenizer's work is a FieldSet. A FieldSet is like a ResultSet for a file. So just like in a ResultSet, we need to reference each "column" by something which in this case is the name. The LineTokenizer has no insight into where the data is ending up (what the object looks like) so we have no way to introspect it. If you wanted to take a more dynamic approach, you'd want to implement your own LineMapper that combines the two functions together allowing for that type of introspection.
As always, pull requests are appreciated!
In addition to Michael Minella's answer, here's what you can do :
You can use a value such as #{jobParameter['key']}, #{jobExecutionContext['key']} or #{stepExecutionContext['key']} in the <property name="names"> tag.
This means that you can have a step or a listener which does your business logic and save the result at any time in the ExecutionContext :
stepExecution.getJobExecution().getExecutionContext().put(key, value);
Keep in mind though, that the field names of a DelimitedLineTokenizer needs a String (well not really, but close enough), not a bean.

Spring MVC: Set property value based on input

I have a login page where I have to select which database it should connect
I have my configuration like this:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
<property name="url" value="jdbc:db2://my_server:10000/DATABASE_1" />
<property name="username" value="galadm" />
<property name="password" value="galadm" />
</bean>
I using Spring JDBC Template
Can I write something like this
<property name="url" value="jdbc:db2://my_server:50000/DATABASE{database_which_I_get_from_input}" />
I don't mind to have initial value i.e. DATABASE_1
Seems that the AbstractRoutingDataSource is a viable solution for you. Its the layer that acts as an intermediary between the multiple datasource, and determines which one to use dynamically.
The following blog solution describes how you can switch based on some attribute of the user’s context
https://spring.io/blog/2007/01/23/dynamic-datasource-routing/

In spring xml config,how to automatically get the current bean's ID value?

I use quartz in spring xml, I have many config like above config~~
I want to known ,automatically get the id value of the current bean
Not every time I hand-written the value of the current bean!!
<bean id="openBaiduTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<bean p:targetObject-ref="baiduManager" p:targetMethod="createOpenBaiDu" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" />
</property>
<property name="cronExpression" value="#{p_schedule['openBaiduTrigger.cronExpression']}" />
</bean>

DBUnit/Spring transaction not rolling back when using OracleDataSource

I'm trying to use DBUnit to insert spatial data into an Oracle database and then roll it back. In order to insert the spatial data, I must use Oracle10DataTypeFactory which pulls in the other DBUnit Oracle extensions for spatial data types. Internally, they will do a cast to an OraclePreparedStatement. In order to get an OraclePreparedStatement, I use an OracleDataSource. So when I use the following Spring configuration:
<bean id="testDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="URL" value="${database.url}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<property name="implicitCachingEnabled" value="false" />
<property name="explicitCachingEnabled" value="false" />
<property name="connectionCachingEnabled" value="false" />
</bean>
The inserts never roll back. I know it is associated with the OracleDataSource from the following testing. Insert a row into a table that does not require spatial data. Use the following configuration:
<bean id="testDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${user}/>
<property name="password" value="${password}"/>
</bean>
Everything works fine and the insert is rolled back at test completion. Perform the same exact test with the OracleDataSource as shown previous, forget it, nothing is rolled back. I've looked at autocommit being set to true, but unfortunately Oracle doesn't provide a method for setting on the OracelDataSource, at least not one I could find. So in my test setup I explicitly set it to false with the following:
connection = DataSourceUtils.getConnection(dataSource);
connection.setAutoCommit(false);
But even that seems to be ignored. Has anybody run into a similar situation?
Spring Role Back only works correct, if a transaction is started.
So make sure that your test uses the Spring Runner (for example by annotating the test with #RunWith(SpringJUnit4ClassRunner.class) ) and the test annotated by #Transactional.

Resources