Monday, 18 April 2016

How to handle Exception in Spring MVC application


Below is one way to handling errors in an spring  MVC  architecture

The class that is given provided below is an ExceptionHandler class which takes care of handing the errors that occurs in the controller and redirect to the error page

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {

private @Value("${debugmode.enabled}") Boolean isDebugModeEnabled;

@ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest request, HttpSession session,  Exception e) throws Exception {
     
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) throw e;
     
        // Otherwise setup and send the user to a default error-view.
        ModelAndView mav = new ModelAndView();
        if(isDebugModeEnabled) {
        mav.addObject("exceptionMessage", e);
        } else {
        mav.addObject("exceptionMessage", null);
        }
        mav.addObject("url", req.getRequestURL());
        mav.setViewName("error");
        return mav;
    }

}

How to configure Ehcache at Entity level in Spring+Hibernate+JPA application

Add the below entries in ehcache.xml which is placed in resources folder incase of maven project and otherwise in the classpath



<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="false" monitoring="autodetect"
         dynamicConfig="true">
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1200" timeToLiveSeconds="1200"     overflowToDisk="true" diskPersistent="false"
     diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/>
   
     <cache name="org.hibernate.cache.internal.StandardQueryCache"  maxElementsInMemory="10000"   eternal="false"   timeToIdleSeconds="3600"  timeToLiveSeconds="3600"/>
  <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"  maxElementsInMemory="10000"  eternal="true"/>  
     <cache name="com.traveldesk.TravelDetail"  eternal="true"  maxElementsInMemory="10000"/>  
</ehcache>


The annotation @cache  helps in making the entity as a cacheable one

@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@Table(name="TRAVEL_DETAIL" , schema="travel")
@NamedQuery(name="TravelDetail.findAll", query="SELECT d FROM TravelDetail d")
public class TravelDetail implements Serializable { }


The properties that are to be provided in the persistence.xml are as follows


<property name="hibernate.cache.region_prefix" value=""/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.generate_statistics" value="true" />
            <property name="hibernate.cache.use_structured_entries" value="true" />                
            <property name="net.sf.ehcache.configurationResourceName" value="META-INF/ehcache.xml" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />



How to configure SLF4j & Logback Logger in Spring+Hibernate applications

Add the below dependencies in the pom.xml

 <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
      </dependency>

 <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
      </dependency>



if it is a maven project , place the below logback.xml in travel-desk\src\main\resources\. Place the **logback-appenders.xml and **logback-loggers.xml in path specified in {-Dapp.configs=c:\<path>}, try to add {-Dapp.configs=c:\<path>} in vm-arguments of  the application server that  you have configured in Eclipse IDE or whichever IDE you use.

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true" scanPeriod="60 seconds" scan="true">

<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>

<!-- To enable JMX Management -->
<jmxConfigurator/>
<include file="${app.configs}/travelDesk/travelDesk-logback-appenders.xml"/>
<include file="${app.configs}/travelDesk/travelDesk-logback-loggers.xml"/>
</configuration>


 Try to add {-Dapp.logs=<path>}  in vm-arguments of  the application server that  you have configured in Eclipse IDE or whichever IDE you use. Below is an snippet from **appenders.xml

/travelDesk-logback-appenders.xml

<included>
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%date{ISO8601} %-5p [%t][%c] %m%n</pattern>
    </encoder>
  </appender>
 
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${app.logs}/travelDesk/travelDesk.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- daily rollover -->
      <fileNamePattern>${app.logs}/travelDesk/travelDesk.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- keep 50 days' worth of history -->
      <maxHistory>50</maxHistory>
    </rollingPolicy>
    <encoder>
      <pattern>%X{NDC0}%X{NDC1}%X{NDC2}%X{NDC3}%date{ISO8601} %-5p [%t][%c] %m%n</pattern>
    </encoder>
  </appender>
</included>


Below are the lines from  **loggers.xml
travelDesk-logback-loggers.xml

<included>
<!-- Loggers -->
<logger name="com.traveldesk" level="debug"/>
<logger name="org.springframework.integration" level="warn"/>

<root level="warn">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</included>










Tuesday, 22 March 2016

How to set deploy explodable in Jboss server

If you come across the issue like creating a empty file called xxxx.war.dodeploy in jboss/standalone/deployments folder then its best to set some extra arguments to make it work.

Under standalone.xml which can found at jboss-eap-6.x\standalone\configuration just append the below one
auto-deploy-zipped="true" auto-deploy-exploded="true"
in the below tag 
<deployment-scanner path="deployments" relative-to="jboss.server.base.dir" 

So that it may look like as below
<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.1">
            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" auto-deploy-zipped="true" auto-deploy-exploded="true"/>
        </subsystem>


This change is advisable to be used used in development or local environment and not in production or other environments.

How to resolve the error "java.lang.IllegalStateException: No transactional EntityManager available"


If you get the below error while using Spring+JPA+Hibernate then try to wrap the method with
import org.springframework.transaction.annotation.Transactional;

@Transactional

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No transactional EntityManager available
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

JBWEB000071: root cause
java.lang.IllegalStateException: No transactional EntityManager available
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:267)
com.sun.proxy.$Proxy39.unwrap(Unknown Source) org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No transactional EntityManager available
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:981)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

JBWEB000071: root cause
java.lang.IllegalStateException: No transactional EntityManager available
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:267)
com.sun.proxy.$Proxy39.unwrap(Unknown Source)

How to call Stored Procedure in JPA 2.1

Repository class is as follows

@NamedStoredProcedureQuery(name = "getBalance", procedureName = "getTravelDetails", resultClasses = { TravelDetail.class }, parameters = {
              @StoredProcedureParameter(name = "travelDate", type = Date.class, mode = ParameterMode.IN),
              @StoredProcedureParameter(name = "travelDestination", type = String.class, mode = ParameterMode.IN),

              @StoredProcedureParameter(name = "travelPackage", type = Integer.class, mode = ParameterMode.OUT),
              @StoredProcedureParameter(name = "travelTimings", type = Integer.class, mode = ParameterMode.OUT)})

public class TravelDetail {    
       private Date travelDate;
       private String travelDestination;
       private String travelPackage;
       private Date travelTimings;

  //gettter & setter methods

}


Class that uses the repository

@PersistenceContext
       private EntityManager entityManager;

       @Override
       public void getTravelDetails(Date travelDate,String travelDestination) {
              StoredProcedureQuery storedProcedure = entityManager
                           .createStoredProcedureQuery("getTravelDetails");

              storedProcedure.registerStoredProcedureParameter("travelDate", Date.class,
                           ParameterMode.IN);

              storedProcedure.registerStoredProcedureParameter("travelDestination", String.class,
                           ParameterMode.IN);

              storedProcedure.registerStoredProcedureParameter("travelPackage",String.class,
                           ParameterMode.OUT);
              storedProcedure.registerStoredProcedureParameter("travelTimings", Date.class,
                           ParameterMode.OUT);
           

              storedProcedure.setParameter("travelDate", "20/02/2015");
              storedProcedure.setParameter("travelDestination", "Mount Alps");

              // execute SP

              storedProcedure.execute();

              String travelPackage =  storedProcedure.getOutputParameterValue("travelPackage").toString();        
           

              Date travelTimings = (Date)storedProcedure.getOutputParameterValue("travelTimings");
           
       }

How to execute procedure in Oracle Sql developer


Use the following query to execute procedure in Oracle Sql developer , procedure that is called should be in a format   <schema_name>.<procedure_name>


 SET SERVEROUTPUT ON
var InParam1 varchar2(100)
var InParam2 varchar2(100)

var OutParam1 NUMBER
var OutParam2 NUMBER


BEGIN  
    :InParam1 := 'A04';
    :InParam2 := '4103640874079701';
 
    travel_schema.travel_detail_proc(:InParam1, :InParam2, :OutParam1,:OutParam2);
 
    dbms_output.put_line('OutParam1=='  || :OutParam1 );
    dbms_output.put_line('OutParam2=='  || :OutParam2 );
    dbms_output.put_line('OutParam3=='  || :OutParam3 );
    dbms_output.put_line('OutParam4=='  || :OutParam4 );
END;
/