Here a code for ajax request to server.
This code defines a function sendRequest(url,divId).
This function takes two arguments, first - the url to which ajax request is to be made. second - the divId in which the response is to be included.
<script>
var http = getHTTPObject();
function sendRequest(url,divId) {
SubmitRBData(url,divId);
}
function SubmitRBData(strUrl,divId) {
http.open("GET", strUrl, true);
http.onreadystatechange = function handleHttpResponse() {
if (http.readyState == 4) {
if (http.status == 200){
results = http.responseText;
document.getElementById(divId).innerHTML=results; // string response
}}};
http.send(null);
}
function getHTTPObject() {
var objXMLHttp=null;
if (window.XMLHttpRequest){
objXMLHttp=new XMLHttpRequest();
}
else if (window.ActiveXObject){
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
return objXMLHttp;
}
</script>
var http = getHTTPObject();
function sendRequest(url,divId) {
SubmitRBData(url,divId);
}
function SubmitRBData(strUrl,divId) {
http.open("GET", strUrl, true);
http.onreadystatechange = function handleHttpResponse() {
if (http.readyState == 4) {
if (http.status == 200)
{
results = http.responseText;
document.getElementById(divId).innerHTML=results; // string response
}
}
};
http.send(null);
}
function getHTTPObject() {
var objXMLHttp=null;
if (window.XMLHttpRequest)
{
objXMLHttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
return objXMLHttp;
}
To make a ajax call, simply include this javascript in your code and call the sendRequest method.
Recently, in one of our project we were using hibernate. We were having hibernate integrated with Velocity, Webwork and Spring. We wanted to show a webpage where the webwork action will make a hibernate query and get the fields from one table. example : We were having a database schema to store countries and cities. The cities were mapped to country. Now our webpage should show all the countries and all the cities within that country. Our hibernate objects were created in such a way that we could retrieve cities from country(One-To-Many). We have also made LAZY loading for cities from country. i.e a country should return cities only when asked. or in other words, the hibernate wont query the database for cities in particular country unless asked.
Since we were using LAZY loading, we faced a problem.
When user sends a request to view page, our webwork action method is called. In this action method we load all the countries, but since cities are lazily loaded, no cities are loaded in action method. In the same action method we open the sesison and query for country and then close the session. Now list of cities is returned to the velocity Parser, but the response is not yet rendered. The velocity page now tries to fetch the cities in each country. Since session is already closed the getter method for cities gives LAZY Initialization Exception. This is because our action method made a query for country and closed the session. When velocity asks for cities and hibernate tries to query for cities, it finds the session to be closed. Hence LAZY initialization error.
This problem can be solved if we open a session on client request and close it before sending a response back to client. This can be achieved with Spring's OpenSessionInViewFilter.
To use OpenSessionInViewFilter, edit your web.xml file and put this filter before webwork filter.
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate.support.OpenSess ionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Issues: Now when you are using OpenSessionInViewFilter, by default the session's flush mode is set to NEVER. So when you try to save something in your action using hibenate and commit it, it wont be reflected in your database. To solve this you need to flush the session in your action class or extend OpenSessionInViewFilter and override closeSession(Session session, SessionFactory sessionFactory).
public MyOSIVFilter extends OpenSessionInViewFilter{
public void closeSession(Session session, SessionFactory sessionFactory){
session.flush();
super.closeSession(session,sessionFactory);
}
}
change your web.xml to
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>package.MYOSIVFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Now it is also possible that you are maintaining a single transaction for per request. In your action you edit the attributes of a object and update it using session.update(object). But it is not yet commited as some other processing is remaining. At the same time, some other request is invoking a action which tries to retrieve the object which you were updating. Since the object is not yet commited the other request will get the old object. To solve this you need to begin a transaction before you load object and commit the transaction after you update the object. So that as soon as the object is saved/updated it is commited. With this there can be many transaction in single user request but only one session.
Now there is another way to do the same thing using Spring TransactionProxyFactoryBean.
This is actually a proxy factory which takes the target object which needs to be proxied, the method to be proxied and the transactionManager.
below is the code snippet from applicationContext.xml
<bean id="repository" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="hibernateTransactionManager"/>
<property name="transactionAttributeSource" ref="transactionAttributeSource"/>
<property name="target" ref="daoImpl"/>
<property name="proxyInterfaces">
<list>
<value>package.DAO</value>
</list>
</property>
</bean>
<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<value>
get*=PROPAGATION_REQUIRED,readOnly
find*=PROPAGATION_REQUIRED,readOnly
create*=PROPAGATION_REQUIRED,readOnly
delete*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
.........................
.............
.....
......
</bean>
<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="daoImpl" class="package.daoImpl">
...................................
..................................
</bean>
Above code says the TransactionProxyFactoryBean that all the methods in daoImpl starting with get, find, create, delete should be proxied and for all this methods the transaction should be begin before method starts and should get commited after method finishes.
We were having a requirement to index PDF document. To index it is necessary to convert it into text form. After searching for some API, we finally got PDFBox which is freeware. Using PDFBox it is very easy to extract text from the PDF document.
Following is the code snippet to extract text from PDF document.
Download PDFBox at http://www.pdfbox.org/
Writer output = new StringWriter();
PDFTextStripper stripper = null;
try {
stripper = new PDFTextStripper();
stripper.setSortByPosition(false);
stripper.setStartPage(1);
stripper.setEndPage(Integer.MAX_VALUE);
PDDocument document = PDDocument.load(path of the file to be read);
stripper.writeText(document, output);
document.close();
} catch (IOException e) {
log.error(e);
e.printStackTrace();
}
return result.toString();
We were having a issue with one of our design. We were having a table which used to store entire file in blob column. When we query a table with some criteria and if the query returns large number of results or the rows and each row containing large blob, we were getting Out of Memory error in Java. To solve this we made a slight modification to our design of tables.
We created two tables file and filecontent and mapped them by one-to-one mapping using hibernate. The blob column was now shifted to filecontent table. We were using lucene to index the content of file. Since blob column was now moved to filecontent table, the indexing which we did on file table didn’t work. To solve this, we used @EmbeddedObject annotation in file object. Our lucene indexing problem was now solved. Indexes were getting created, but now the same problem occurred again. The hibernate-lucene in turn does a join query when we search through index. As a result again the huge blob is getting retrieved along with other columns. To solve this we again changed our design, but this time only in hibernate configuration.
We created a transient field of type byte[] in file object and made it indexable. So we were having the file’s content in two object (file and filecontent), but in file it was transient and indexable and in filecontent it was persistent and non-indexable.
Also while mapping file and filecontent object using hibernate, we specified LAZY loading filecontent object.
By default, in MySQL we can store BLOB of size 1M. To increase the size of this you have to change the my.conf file.
You can find my.conf file in Program Files\MySQL\MySQL Server 5.0\my.ini
Open the file and Under the [mysqld], add the following line.
max_allowed_packet = 16M
eg:
[mysqld]max_allowed_packet = 16M
When we store any file in database in the blob column, we would also want it to be downloaded as and when required by webpage.
To achieve this we can write a servlet or a action in Webwork that makes this facility available. In the servlet we write the jdbc code to get the blob column in bytes[] format. Once we have file content in bytes[] we can add it to the response using OutputStream. Also if we want to give a name to file we can set the header in the response. Following is the code which will show how to do this.
----------- jdbc code to get the blob column ---------
bytes[] content= //get the blob using jdbc or any persistent framework.
doPost(ServletRequest req, ServletResponse res){
HttpServletResponse response=(HttpServletResponse)res;
response.setContenType("application/doc");
response.addHeader("Content-Disposition", "attachment;filename=file.doc");
ServletOutputStream output = response.getOutputStream();
output.write(content);
}
Generally when we want to delete any row from database using hibernate, we first load the object using session.load(Class,Long). We then delete the object retrieved for id using session.remove(object).
The problem with this approach is that Hibernate first fires a select query to the database to get the object(row). After it gets the object hibernate then fires a delete query to delete the row. So, do one operation on database, we are making hibernate to fire two queries.
Also another problem associated with this approach is that if the object of class(Table) which we want to delete may have join to other tables. In such scenario, when we are loading the object using session.load the join query is fired which is heavy.
The ideal approach would be create a hibernate query for deleting the object(row). In this approach hibernate will only fire single delete query. As only one query if fired, the time taken taken would be less.
eg:
Normal approach to delete using hibernate
MyTable table= (MyTable)session.load(MYTable.class,new Long(2);
session.remove(table);
session.flush();
session.close();
IDeal Approach to delete single row using hibernate
session.createQuery("delete from MyTable where id=2").executeUpdate();
session.fluch();
session.close();
To search through indexes using your java code is easy. You can search through your indexes created by lucene using lucene API. Lucene-core-2.2.0.jar.
Following is the code usage showing how to search through lucene index.
IndexReader reader = null; reader = IndexReader.open("C:\var\lucene\indexes\Document");
(path of your lucene index i.e. segments.gen)
Searcher searcher = new IndexSearcher(reader); Analyzer analyzer = new StandardAnalyzer();
MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[]{"content", "title", "description"}, analyzer);
Note : ('content','title','description' are the fields which we want to search in index)
Query query = parser.parse('searchString'); Hits hits = searcher.search(query);
Once you get the hits object you can find any data that is saved in index using the hits object.
We were having a requirement to upload documents form webpage which could be of more than 2M. By default the webwork supports only uploading max 2M of file. To increase these size, you need to change the settings at two place. These two places are webwork.properties file and xwork.xml file
Put this setting in webwork.properties
webwork.multipart.maxSize=4194304 //this denotes 4M (specify as per your requirement)
Put this setting in xwork.xml
<interceptor-ref name="fileUpload">
<param name="maximumSize">4194304</param>
</interceptor-ref> //this denotes 4M (specify as per your requirement)