hibernate + Oracle 11.2 + BLOB - oracle

I googled a lot and haven't found working issue... In my web app I need to upload large files using ajax. I use ajaxfileupload plugin for it. In my FormBean class I mapped file to InputStream:
private InputStream fileData;
and
#FormParam("file")
#PartType("application/octet-stream")
#JsonIgnore
public void setFileData(InputStream fileData) {
this.fileData = fileData;
}
It works fine. I can save this stream into a file and haven't got any problems with java heap size. Now I'm trying to save it into database using Hibernate. Like this:
repFile.setFileData(session.getLobHelper().createBlob(file.getFileData(), 1024L));
and when I save repFile object I have ORA-01461 can bind a LONG value only for insert into a LONG column.
It works with Oracle 10. But it crashes with Oracle 11.2
I tried to add lobHandler to my configuration - didn't help
<property name="lobHandler">
<bean class="org.springframework.jdbc.support.lob.OracleLobHandler">
<property name="nativeJdbcExtractor">
<bean class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"/>
</property>
</bean>
</property>
And set batch size to 0 and allow steams
<prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
<prop key="hibernate.jdbc.batch_size">0</prop>
That didn't help also... does anyone have a solution for this? Any help would be good.

You need to map the domain class like this:
#javax.persistence.Lob
private java.sql.Blob fileData;
Also, make sure that you create the column in the database as a 'BLOB'.
Finally, I recommend that you do not use 'InputStream' in your FormBean, but instead use something like 'MultiPartFile', since you can read an InputStream only once (unless you rewind/reset it). Also, MultiPartFile will give you the filename and length.

Related

Call a bean method with the downloaded filename after file download using sftp outbound gateway

I am using int-sftp:outbound-gateway to download remote files. File download is working. I need to call another method after file is downloaded for both success as well as failure. In that method I need status (success or failure) and name of the file that was requested to be downloaded. Then from that method I will initiate a post download flow depending on the status like - moving file to different location, notifying the user, sending email, etc.
I have used AfterReturningAdviceInterceptor to call my own method defined in MyAfterReturningAdvice which implements AfterReturningAdvice interface. With this my method to initiate the post download flow. It does execute and I do get filename in GenericMessage's payload. My question is, do we have a better way to implement this flow.
I tried using ExpressionEvaluatingRequestHandlerAdvice's onSuccessExpression but from that I cannot call another method. All I can do is manipulate the inputMessage(GenericMessage instance).
In future sprints I will have compare checksum of downloaded file with expected checksum and re-download file for a fixed number of times if there is checksum mismatch. As soon as checksum matches I again need to call post download flow. If the download fails even at last retry, then I need to call another flow (send email, update db, notify user of failure,etc.)
I am asking this question just to make sure that my current implementation fits overall requirements.
<int:gateway id="downloadGateway" service-interface="com.rizwan.test.sftp_outbound_gateway.DownloadRemoteFileGateway"
default-request-channel="toGet"/>
<bean id="myAfterAdvice" class="org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor">
<constructor-arg>
<bean class="com.rizwan.test.sftp_outbound_gateway.MyAfterReturningAdvice">
</bean>
</constructor-arg>
</bean>
<int-sftp:outbound-gateway id="gatewayGet"
local-directory="C:\sftp-outbound-gateway"
session-factory="sftpSessionFactory"
request-channel="toGet"
remote-directory="/si.sftp.sample"
command="get"
command-options="-P"
expression="payload"
auto-create-local-directory="true">
<int-sftp:request-handler-advice-chain>
<ref bean="myAfterAdvice" />
</int-sftp:request-handler-advice-chain>
</int-sftp:outbound-gateway>
public class MyAfterReturningAdvice implements AfterReturningAdvice {
#Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
//update db, send email, notify user.
}
}
The ExpressionEvaluatingRequestHandlerAdvice.onSuccessExpression() is the best choice for you. Its EvaluationContext is BeanFactory-aware, therefore you definitely can call any bean from that expression. The Message provided there as a root object is a good candidate to get an information about a downloaded file.
So, this is what you can do there:
<bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
<property name="onSuccessExpressionString" value="#myBean.myMethod(#root)"/>
</bean>
The same you can do with the onFailureExpression.
On the other hand you may even don't need to worry about the bean access from the expression. The ExpressionEvaluatingRequestHandlerAdvice has successChannel and failureChannel options. So, the message with the result can be send there and some <service-activator> with your bean can handle a message on that channel.

Placeholder of Camel from tag is not getting updated with new values

I have my publicAddress property defined in Spring XML and using it in Java DSL(Route builders). Value of 'publicAddress' comes from Web GUI.
<util:properties id="service-properties">
<prop key="publicAddress"></prop></util:properties>
I was previously using Camel 2.10 and have switched to 2.15.
Following code is used to create Route builders which has different public addresses. With this code in place, if I create second Route builder, value of 'publicAddress' does not gets updated. RouteBuilder gets created with old value of 'publicAddress'
from(abcd+ ":"+ serviceName+ "://{{publicAddress}}?loggingEnabled= {{loggingEnabled}}").routeId(xyz + serviceName + "Route");
I tried using service-properties:{{publicAddress}} but that gave me null value.
Any idea which placeholder I need to use to resolve this issue ?

Accesing Property files in Spring

I am new to spring and I am trying to read the values from properties file.
This is my Security XML:-
<beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<beans:property name="location">
<beans:value>AuthProvider.properties</beans:value>
</beans:property>
</beans:bean>
and I am trying to access the properties in java class as follows but its returning nothing:
Properties props = PropertiesLoaderUtils.loadAllProperties("AuthProvider.properties");
PropertyPlaceholderConfigurer props2 = new PropertyPlaceholderConfigurer();
props2.setProperties(props);
for(String key : props.stringPropertyNames())
{
String value = props.getProperty(key);
System.out.println(key + " => " + value);
}
Can someone please tell me where I am goin wrong?
First of all you should show the error you get.
From other side to understand more it is better to read books and docs about a framework.
Regarding Spring you can find enough info here: https://spring.io/guides
Right now it isn't clear what is your general task.
To have just properties as bean it is enough to use:
<util:properties id="myProps" location="AuthProvider.properties"/>
However you shouldn't forget that there is need to correctly specify the location for your file: is it on classpath, on file system, some external URL etc. Here is more info: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html
At the same reference you can find out how to configure <property-placeholder> and why it is needed.
UPDATE
Just to load properties from file to the Properties object you do it correctly using PropertiesLoaderUtils.loadAllProperties. But here the resourceName should be correct relative path to the file within CLASSPATH - and it will be loaded as resource by ClassLoader.
What is bad here, we don't know where is your AuthProvider.properties, and it says that you provide for it the wrong path.

How to add date and time to the file name

I am working on the JasperReports using Spring. I am giving the chance to customer to download the report in pdf and csv formats. But my requirement is in download prompt i need to show the file name with date and time. But I am able to show only the file name. How can I show the file name with date and time while downloading?
I am using the below code in my jasper-views.xml:
<bean id="test-pdf"
class="org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView"
p:url="classpath:reports/testreport.jrxml"
p:reportDataKey="datasource">
<property name="headers">
<props>
<prop key="Content-Disposition">
attachment; filename=TestReport.pdf
</prop>
</props>
</property>
</bean>
How can i add date and time to the file name while downloading?
before writing your stream , set the file name :
response.setHeader("Content-Disposition", "inline; filename=" + fileName);
in the file name , you can set your date dynamically :)
and this link may be useful :
securly-download-file-inside-browser-with-correct-filename
In your example, you're able to show the filename because you can also specify what the filename should be when you actually generate the report. If you want to display the date and time the report is generated, and the report is generated when they press some button to download the report, you're really just displaying the current time. I don't know what value there is in that, but if it's necessary, just use some javascript to continually update the current time in their browser, maybe using a timer that fires once a minute to update the displayed time.

How can I configure the indexes for using db4o with Spring?

I'm currently evaluating the Spring-db4o integration. I was impressed by the declarative transaction support as well as the ease to provide declarative configuration.
Unfortunately, I'm struggling to figure how to create an index on specific fields. Spring is preparing the db during the tomcat server startup. Here's my spring entry :
<bean id="objectContainer" class="org.springmodules.db4o.ObjectContainerFactoryBean">
<property name="configuration" ref="db4oConfiguration" />
<property name="databaseFile" value="/WEB-INF/repo/taxonomy.db4o" />
</bean>
<bean id="db4oConfiguration" class="org.springmodules.db4o.ConfigurationFactoryBean">
<property name="updateDepth" value="5" />
<property name="configurationCreationMode" value="NEW" />
</bean>
<bean id="db4otemplate" class="org.springmodules.db4o.Db4oTemplate">
<constructor-arg ref="objectContainer" />
</bean>
db4oConfiguration doesn't provide any means to specify the index. I wrote a simple ServiceServletListener to set the index. Here's the relevant code:
Db4o.configure().objectClass(com.test.Metadata.class).objectField("id").indexed(true);
Db4o.configure().objectClass(com.test.Metadata.class).objectField("value").indexed(true);
I inserted around 6000 rows in this table and then used a SODA query to retrieve a row based on the key. But the performance was pretty poor. To verify that indexes have been applied properly, I ran the following program:
private static void indexTest(ObjectContainer db){
for (StoredClass storedClass : db.ext().storedClasses()) {
for (StoredField field : storedClass.getStoredFields()) {
if(field.hasIndex()){
System.out.println("Field "+field.getName()+" is indexed! ");
}else{
System.out.println("Field "+field.getName()+" isn't indexed! ");
}
}
}
}
Unfortunately, the results show that no field is indexed.
On a similar context, in OME browser, I saw there's an option to create index on fields of each class. If I turn the index to true and save, it appears to be applying the change to db4o. But again, if run this sample test on the db4o file, it doesn't reveal any index.
Any pointers on this will be highly appreciated.
Unfortunately I don't know the spring extension for db4o that well.
However the Db4o.configure() stuff is deprecated and works differently than in earlier versions. In earlier versions there was a global db4o configuration. Not this configuration doesn't exist anymore. The Db4o.configure() call doesn't change the configuration for running object containers.
Now you could try to do this work around and a running container:
container.ext().configure().objectClass(com.test.Metadata.class).objectField("id").indexed(true);
This way you change the configuration of the running object container. Note that changing the configuration of a running object container can lead to dangerous side effect and should be only used as last resort.

Resources