August 02, 2015

SpringMVC: PropertyPlaceHolder

Another interesting support feature provided by Spring is using properties in your code through PropertyPlaceholderConfigurer. It helps load application properties from either a file or database table. The XML for using both,which will go into your spring context file,is 

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="properties">
        <bean class="org.apache.commons.configuration.ConfigurationConverter"
             factory-method="getProperties">
                 <constructor-arg>
                   <bean class="org.apache.commons.configuration.DatabaseConfiguration">
                          <constructor-arg ref="<database bean>" />
                          <constructor-arg value="<database property table>" />
                          <constructor-arg value="<tablecolumn for placeholdernames>" />
                          <constructor-arg value="<tablecolumn for placeholdervalues>" />
                   </bean>
                </constructor-arg>
        </bean>
     </property>
     <property name="locations">
         <list>
            <value>file:src/main/webapp/WEB-INF/application.properties</value>
         </list>
     </property>
</bean>

<constructor-arg value="datasource" /> refers to a database bean defined in the spring context xml.

<constructor-arg value="app_config" /> refers to a database table APP_CONFIG.

<constructor-arg value="config_key" /> refers to column 'CONFIG_KEY' in APP_CONFIG that will contain the property you want to use in your code.

<constructor-arg value="config_value" />  refers to column 'CONFIG_VALUE' in APP_CONFIG that will contain the corresponding value of the property.


The below example shows how to then use the pre-loaded properties in your Spring code.


@Controller
public class DocumentController{

     @Value("${doc_Base}")
      String docBase="";
      @Value("${app_Env}")
      String appEnv=null;
      @Value("${doc_Path}")
      String docPath="";

      @Autowired
      private DocumentDAO documentDao;

      @Autowired
      private UserDAO userDao;

      @RequestMapping(value="/upload")
      public String uploadDocument(@RequestParam("docName)String documentName,
                                  @RequestParam("docFile")MultipartFile file)
      {
         <upload logic>

     }
       

}

The members docBase,appEnv & docPath will be initialized when the Controller instance gets created. Here doc_Base,app_Env & doc_Path are property names defined in CONFIG_KEY & their corresponding values in CONFIG_VALUE will be used for initialization

CONFIG_KEY       CONFIG_VALUE
doc_Base              test
app_Env               Dev
doc_Path              /dev/reviews



References

http://forum.spring.io/forum/spring-projects/container/82142-propertyplaceholderconfigurer-problems

July 04, 2015

Spring MVC: PagedListHolder



Spring 3 MVC framework provides supporting classes/annotations that can prove to be real "gems" during development of your web application. I'll be covering a few of them, the first being "PagedListHolder".


PagedListHolder


Spring Framework comes with a bean called org.springframework.bean.support. PagedListHolderAs per documentation, PagedListHolder is a simple state holder bean for handling lists of objects, separating them into pages. It has setter methods to indicate page size, page number.

For e.g in your specific Controller class you can add the following code snippet to create paginated data that can be accessed in a JSP or any other View.



 


String srchkey= request.getParameter("srchkey");
if (srchkey!= null) 
{
 PagedListHolder<Product> productList = new PagedListHolder<Product>(getProductList(srchkey)); 
productList.setPage(0);
        productList.setPageSize(4);        request.getSession().setAttribute("productList", productList); 
        return new ModelAndView("ListProducts", "productList", productList);    
}
else 
{ 
        String page = request.getParameter("page"); 
        PagedListHolder productList = (PagedListHolder)request.getSession().getAttribute("productList"); 

        if ("next".equals(page)) 
            productList.nextPage(); 

        else if ("previous".equals(page))
            productList.previousPage();
       
        return new ModelAndView("ListProducts", "productList", productList);    
}




References

http://stackoverflow.com/questions/2245035/how-to-implement-pagination-in-spring-mvc-3




Use AJAX to access JSON from a Struts2 Action class



If there is a use-case wherein a HTTPRequest invokes a Struts2 Action class to perform an action & its output is then to be received by an AJAX function on the target webpage, for e.g.population of data rows in an HTML table, then this is one approach to do it

1. Send the output of the Struts2 Action class as a JSON object. 


 Let's say we have an Action class 'JSONResponseAction.java' that is required to send a Java bean 'ResponseVO.java' ( it has 2 String fields- a status & a message) as a JSON object to client e.g a browser. 

public class JSONResponseAction extends BaseActionSupport
{

public ResponseVO responsVO;


public String load() throws IOException, ServletException
{
   
responseVO=new ResponseVO();
responseVO.setStatus("success");
responsVO.setMessage("Process completed");

}

public ResponseVO  getResponseVO() 
{
    return responseVO;
}

public void setResponseVO(ResponseVO responseVO) 
{
    this.responseVO= responseVO;
}

}

It is mandatory that setter & getter methods be present for 'ResponseVo' bean in the Action class for corresponding JSON object to be created & sent across the n/w. We can also use the default 'execute()' method of Struts2 Action class for this. In that case,We will not have to explicitly mention the method-name in the request URL in pt.3

2. In the struts.xml, we define an action 'JSONResponseAction.action' as follows

  <action name="JSONResponseAction"  class=JSONResponseAction>
  <result name="success" type="json">
     <param name="root">
             responseVO
  </param>
  <result name="failure">/error.jsp</result>
  <interceptor-ref name="defaultStack"/>
 </action>


3. On the client side, we can have JQuery code, something similar to what I have written below, to access 'ResponseVO'.



$.getJSON( "${pageContext.request.contextPath}/JSONResponseAction.action?method:load",
{<requestparamName>:<requestParamvalue>},
function(responseVO) {

     //Jquery or Javascript code to use 'ResponseVO'


});

4. We can also send an array of 'ResponsVO' beans in a similar fashion

public class JSONResponseAction extends BaseActionSupport
{

public ResponseVO[] responseVO;

public String load() throws IOException, ServletException
{
  //populate the array

}
public ResponseVO[]  getResponseVO() 
{
    return responseVO;
}

public void setResponseVO(ResponseVO[] responseVO) 
{
    this.responseVO= responseVO;
}

}


April 23, 2015

CallableStatement.setObject() SQLException - Fail to construct descriptor: Invalid arguments


Oracle supports structured user-defined types or UDTs.  JDBC 2.0 provides an ability to custom map a Oracle UDT using a Java class. The class will have a field for each attribute in the UDT. The class has to implement java.sql.SQLData  & Serializable interfaces. There are other techniques available such as the ORAData and ORADataFactory interfaces provided by Oracle but this post deals with SQLData.

Let's say, you have a UDT  'OBJ_USER' that has the following attributes - userid, username and corresponding Java mapper class called UserObj.java

CREATE OR REPLACE TYPE OBJ_USER
  (
    USERID NUMBER,
    USERNAME VARCHAR(40)    
  );

public class UserObj implements SQLData,Serializable {

     private long userID;
     private String userName;
    private String sql_type;
}


Now we can persist & read data using UDT and its corresponding Java mapper object. The 'SQLData' interface provides two methods for this

@Override
public void writeSQL(SQLOutput stream) throws SQLException 
{
    stream.writeLong(userId);            
    stream.writeString(userName);
             
 }

@Override
public void readSQL(SQLInput stream,String typethrows SQLException 
{
    sql_type= type;
    userId=stream.readLong();            
    userName=stream.readString();
             
 }


The following code calls a StoredProcedure using a JDBC CallableStatement instance that will persist the UDT data to a table ( We don't need to worry about that since  focus here is the JDBC approach to map data)


conn =  createConnection();
String schname = <SCHEMA>;
             
System.out.println("conn::" + conn);
Map map = conn.getTypeMap();
System.out.println("SchemaName:" + conn.getMetaData().getUserName());
map.put(schname + ".OBJ USER", Class.forName("UserObj"));
                                 
cstmtForCMValidation = conn.prepareCall("{call <package_name>.<procedure_name>(?,?,?)}");
cstmtForCMValidation.setObject(1, userObj);                                                                                                          

However, 'setObject(1, userObj)' call can throw the following exception

java.sql.SQLException: Fail to construct descriptor: Invalid arguments
       at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
       at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
       at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
       at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:263)
       at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:271)
       at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:161)
       at oracle.sql.StructDescriptor.createDescriptor(StructDescriptor.java:137)
       at oracle.sql.STRUCT.toSTRUCT(STRUCT.java:477)
       at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:7954)
       at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:7547)
       at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8037)
       at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4132)
       at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:238)


To fix this exception, the 'UserObj.java'  field - sqltype  will have to be set with UDT name either in the constructor or its setter e.g

 public UserObj (){
   sql_type=SCHEMA+".OBJ_USER";
}

Note: this field has to be set with the fully qualified name of the UDT i.e. with DB schema name

This is because while writing data from the mapper object to the UDT, CallableStatement instance will not look for mapping relation in the 'Type' Map of JDBC Connection object. It will check the value of sqltype field of mapper object.

February 26, 2015

AbstractAnnotationConfigDispatcherServletInitializer conflict with web.xml for Spring Security


When we use Spring Security in our application, we  extend 
AbstractAnnotationConfigDispatcherServletInitializer 
to include our WebSecurityConfigurerAdapter implementation into the root context.


However this can throw the following error during application startup

"Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your webxml!"

One reason the above may happen is because we could be having the following snippet in our web.xml

<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param> 

which already creates the root context for the Application from
/WEB-INF/applicationContext.xml.


Servlet 3.X specification allows us to do away with XML and create Java-based configuration. So we can comment the above snippet in web.xml and add the following method in our AbstractAnnotationConfigDispatcherServletInitializer subclass to remove the above error.


@Override
protected WebApplicationContext createRootApplicationContext() {
// TODO Auto-generated method stub
return new XmlWebApplicationContext();
}

The no-arg XmlWebApplicationContext instance uses
"/WEB-INF/applicationContext.xml" by default.



September 29, 2014

Lifecycle of a JSP- part I



JSPs are basically dynamic HTML pages, the dynamic content being provided by specific libraries(JSTL or Java Standard Tag Libraries ) expressions and directives ( page,import,include ). The specifics of these elements I will discuss in future posts.

This post will deal with the life-cycle of a JSP  in Apache Tomcat. The questions that will be answered will be
  • Does a JSP get converted in .java file. If so,when ? during server start-up or every time a JSP page is requested by the browser.
  • Which component of Tomcat does the conversion? Where does this so call JSP engine reside in Tomcat?
  • What happens after the conversion ? Where do the converted files reside ? 
  • When does a JSP page finally get destroyed ?
  • Dynamic and Static inclusion


So let's begin with answering the first question:

Yes. A JSP page gets  translated into a Servlet java file and corresponding class file.This is known as the translation & compilation phase. 

e.g. login.jsp --> login_jsp.java --> login_jsp.class

The java and class files are stored in 'work' directory in Tomcat

Now, these 2 phases can happen when the application is deployed. The container translates & compiles all jsp into class files. This is called pre-compilation and provides better performance since time is not spent during page request.

But these 2 phases can also happen when a request for jsp is made. The container checks if the jsp file is newer than the class file. if it is, then it translates & compiles again before serving the request.

Sometimes, a jsp file needs to be included into another jsp file. This can be done by

<%@include directive or <jsp:include action

The difference b/w the two is that using the former, the jsp gets included into its parent jsp during application deployment & hence is  best suited for including static content. That's why only relative path w.r.t the parent jsp is enough for inclusion e.g

<%@include file="./footer.jsp" %>   if parent jsp and footer.jsp are in same directory.

Using the latter,the jsp gets included during request time i.e. when the client requests the parent jsp file. This is called dynamic inclusion and is suited for jsp with lot of dynamic content. This include action also can cause performance overhead since inclusion happens at run time. So use it wisely i.e.for including jsp with a lot of dynamic content.

Also, since inclusion happens at run time, the context relative path is used.

<jsp:include page=/XXX/footer.jsp />  if footer.jsp is present in dir 'XXX' of the web-application

July 30, 2014

page redirect in Javascript


JavaScript Location Object also have these three methods
  1. assign() -- Loads a new document.
  2. reload() -- Reloads the current document.
  3. replace() -- Replaces the current document with a new one
You can use assign() and replace methods also to redirect to other pages like these
window.location.assign("http://www.stackoverflow.com");

window.location.replace("http://www.stackoverflow.com");
The difference between replace() and assign()  is that replace() removes the URL of the current document from session history, means it is not possible to use the "back" button to navigate back to the original document. So use the assign() method if you want to load a new document, and also want to navigate back to the original document.
Apart from the above,
window.location.href = "http://stackoverflow.com";
This is basically simulating the click of a link

Reference