Tuesday, February 21, 2012

Audit Log to database Using Spring AspectJ Oriented Programming And Annotation.

Create a Aspect class.

@Aspect
@Component
public class AuditAspect {

@AfterReturning(value = "@annotation(audit)", returning = "returnParameter", argNames = "joinPoint, audit, returnParameter")
public void afterReturning(JoinPoint joinPoint, Audit audit, Object returnParameter) {
StringBuffer buffer = new StringBuffer();
for (Object object : joinPoint.getArgs()) {
if (null != object && "" != object) {
buffer.append(object.toString());
buffer.append(", ");
}
}

String outparam = null;
if (null != returnParameter && (returnParameter instanceof Map || returnParameter instanceof List)) {
outparam = "";
} else if (null != returnParameter) {
outparam = returnParameter.toString();
}

addAuditLog(joinPoint.getSignature().getName(),
buffer.toString(),
outparam,
this.userService.getLoggedinUser().getExternalId(),
String.valueOf(joinPoint.getStaticPart().getId()),
joinPoint.getTarget().toString(),
joinPoint.getStaticPart().getKind().toString());


logger.info("Ending Method: [" + joinPoint.getSignature().getName() + "]");
}

@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.DEFAULT, rollbackFor = {HibernateException.class, AppException.class})
private void addAuditLog(String actionType, String metaDataIn, String metaDataOut, String actorId, String entityId, String entityName, String entityProperty) {
try {
AuditLog auditLog = new AuditLog();
auditLog.setRelevanceTime(new Timestamp(Calendar.getInstance().getTime().getTime()));
auditLog.setOperationType(actionType);
auditLog.setEntityPropertyNewValue(metaDataIn.length() > 255 ? metaDataIn.substring(0, 255) : metaDataIn);
auditLog.setEntityPropertyOldValue(metaDataOut.length() > 255 ? metaDataOut.substring(0, 255) : metaDataOut);
auditLog.setActorId(actorId);
auditLog.setEntityId(entityId);
auditLog.setEntityName(entityName);
auditLog.setEntityProperty(entityProperty);
this.daoFactory.getAuditLogDAO().makePersistent(auditLog);
} catch (Exception e) {
logger.error("Error occurred while adding audit log {}", e.toString());
}
}

@Before(value = "@annotation(com.nvsoft.csk.service.audit.Audit)", argNames = "joinPoint")
public void before(JoinPoint joinPoint) {
logger.info("Beginning method: [ " + joinPoint.getSignature().getName() + " ]");
}

@AfterThrowing(value = "@annotation(com.nvsoft.csk.service.audit.Audit)", throwing = "ex", argNames = "joinPoint, ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
logger.info("Exception in method: [ " + joinPoint.getSignature().getName() + " ] Exception is: [" + ex.getMessage() + " ]");
}


public AuditInterceptor() {
logger.debug("Instantiating the AuditInterceptor");
}

@Autowired
public AuditInterceptor(DAOFactory daoFactory) {
this.daoFactory = daoFactory;
}

private DAOFactory daoFactory;

@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}

private UserService userService;
public static Logger logger = LoggerFactory.getLogger(AuditInterceptor.class);

}



Create annotation with Audit

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Audit {
}


My ApplicationContext xml file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<bean id="myDAOFactory" class="com.nvsoft.csk.dao.hibernate.HibernateDAOFactory">
<property name="sessionFactory">
<ref bean="serverSessionFactory"/>
</property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="serverSessionFactory"/>
</bean>


<!--
Turn on AspectJ @Configurable support. As a result, any time you
instantiate an object, Spring will attempt to perform dependency
injection on that object. This occurs for instantiation via the "new"
keyword, as well as via reflection. This is possible because AspectJ
is used to "weave" applications at compile time. In effect
this feature allows dependency injection of any object at all in your
system, which is a very useful feature (without @Configurable you'd
only be able to dependency inject objects acquired from Spring or
subsequently presented to a specific Spring dependency injection
method). Applications use this useful feature in a number of
areas, such as @PersistenceContext injection into entities.
-->
<context:spring-configured/>

<!-- It will scan all annotated classes -->
<context:component-scan base-package="com.nvsoft.csk">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

<!-- Annotation based transaction-->
<tx:annotation-driven transaction-manager="txManager"/>

<aop:aspectj-autoproxy/>
<!-- For hashing and salting user passwords -->
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource"
p:userPropertyToUse="id"/>

<!-- Velocity Engine configuration for email template -->
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"
p:resourceLoaderPath="classpath:/emailTemplate/,classpath:/xhtmlTemplate/,classpath:/smsTemplate/"
p:preferFileSystemAccess="false"/>

<!-- mailSender properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"
p:host="${email.host}"
p:username="${user.email.address}"
p:password="${user.email.password}">
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
<prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
</props>
</property>
</bean>

<!-- Definition of template message if nothing is specified from the code then default properties are going to
pick from here -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage"
p:from="${user.email.address}"
p:to="${user.email.address}"
p:subject="Greetings from S2Pay"/>

</beans>


I have Service class as CouponManager and i have annotated method createCoupon with @Audit and the aspect get trigger whenever i execute the createCoupon method and logs the information in the audittable

@Service("couponService")
public class CouponManager implements CouponService {
@Audit
@Transactional
@Override
public AbstractCoupon createCoupon(CouponForm form) {
//do whatever your businessLogic
return coupon;
}
}

Hope this information will helps whoever want to incorporate spring aspect oriented feature in their project

Tuesday, January 31, 2012

Auto Complete feature of dijit.form.FilteringSelect using Ajax and dojo.data.ItemFileWriteStore

Using Dojo widgets FilteringSelect and ItemFileWriteStore we can build a autocomplete or hint text feature for a input text box

Javascript is as follows

<script type="text/javascript">
<![CDATA[
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.form.FilteringSelect");
dojo.require("dijit.form.Button");
var couponStore;
dojo.addOnLoad(function () {
dojo.connect(dijit.byId('couponSelect'), 'onKeyUp', function () {
var xhrArgs = {
url: "/WebAdmin/report/coupon/"+ dojo.byId('couponSelect').value,
handleAs:'json',
load: function(data) {setData(data);},
error: function(error) {
dijit.byId('couponSelect').innerHTML= "An unexpected error occured" + error;
}
};
var items = dojo.xhrGet(xhrArgs);
function setData(items) {
couponStore = new dojo.data.ItemFileWriteStore({
data : {identifier:'name', items: items.items}
});
}
dijit.byId('couponSelect').set('store',couponStore);
});
});
]]>
</script>


The HTML declarative code is as follows

<div id="couponStore" dojoType="dojo.data.ItemFileReadStore" jsId="couponStore" url="/WebAdmin/report/coupon/test"/>
<form:select id="couponSelect" dojoType="dijit.form.FilteringSelect" store="couponStore" path="name" />


URL is mentioned in ItemFileWriteStore so by default it load some data into the FilteringSelect Widget.


Server Side looks something like this below
@ResponseBody
@RequestMapping(value = "/report/coupon/{coupon}")
public String filterCouponNames(@PathVariable("coupon") String name) throws JSONException {
log.info("Coupon name = {}", name);
JSONObject respObject = new JSONObject();
List<JSONObject> list = new ArrayList<JSONObject>();
List<AbstractCoupon> coupons = service.findCouponByFilter(name);
for (AbstractCoupon coupon : coupons) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", String.valueOf(coupon.getCouponId()));
jsonObject.put("name", coupon.getName());
jsonObject.put("type",coupon.getCouponType());
list.add(jsonObject);
}
respObject.put("identifier","name");
respObject.put("items",list);
log.info(respObject.toString());
return respObject.toString();

}

Hope this information is helpful to someone who is looking to integrate auto complete feature using dojo.

Thursday, January 26, 2012

Wednesday, January 25, 2012

My Brother-in-Law Wedding

I will remember my brother - in - law wedding took 8 extra days leave from work and compensate with loss of pay for 5 days for month of November. But the wedding event was memorable. We enjoyed a lot, dance lot drunk lot everything lot.

Here is some of the memories to cherish.

Tuesday, January 17, 2012

Explore to RatnaGiri & Ganpatipule

Our 1st halt was at Vithal Kamath on Mumbai - Goa road at 8:20 AM after 2hrs 30 mins of drive. We had our breakfast at Kamath. Decent preparation of South Indian food. Few pics taken at Vittal Kamath halt.




We resumed our journey at 9:10AM and headed towards Ratnagiri. We reached Chiplun around 10:45 AM took at quick tea break for 10 mins and then move towards Ratnagiri at 12:00PM we reached Hathkhamba and that is place where we took right diversion to get towards Ratnagiri. About 2kms - 3Kms approx of travel we reach Ratnagiri city.

Ratnagiri is clean and small town at Konkan parts of Maharastra. We visited to TheBaw palace though there is nothing much to see but there was a museum inside TheBaw palace. There was entry fee of Rs 3.00 for adults and Rs 1.00 for kids below 8 years.
Musuem has belonging of King TheBaw and there were some very old sculptures. Photography was banned inside the palace.


TheBaw Palace




Pots from Museum inside TheBaw palace

Then we headed towards next point which is adjacent to TheBaw palace called TheBaw point also called the Sunset point or Garden point. Very nice view from here. And the park is small but maintained well. To enter to the park there is entry fee of Rs 10/- for adults and for kids free.


View infront of TheBaw point


Views from TheBaw point


We can see near village of Ratnagiri from this place and lots of Fishermen locality (Koli) people inhabits from this point.

Fishering boats


Park view


Ratnagiri also have a small Aquarium with good collection of underwater animals.
They charge Rs 10 for adult and Rs 3 for kid. Also if you take picture inside the aquarium they charge some fees for photography.



Around 2:30PM, We found a Malawan restaurant "Vikas Malwani lajja". We had Chicken thali are awesome also the Malwan Vada are delicious. After good lunch we headed towards Ganpatipule, which is 23 KM from Ratnagiri. Roads are narrow but they are maintained the views is very nice. Some of the pictures taken while travelling towards Ganpatipule.

Early morning 5:35AM we started from Kamothe Sector -17. Climate was cool and traffic were less in Mumbai - Goa road. The distance from Kamothe to Ratnagiri was 336KM. We followed google maps and move on. direction

We checked in at hotel Shri Sagar at Ganapatipule. Rooms are good and it has garden restaurant as well.

Then evening we went to beach and temple darshan of Ganpatipule.

Day-2

After having breakfast we left hotel at 11AM and then we went to temple again.



We spent 30 mins near beach and had some good pictures of Camel at the beach.




Then around 11:45 we drove towards Jaigad fort reached Jaigad after an 1hr. Roads are very narrow cant drive more than 50 KMPH.


Entrance of Jaigad fort


Inside view Jaigad fort


Jaigad was our last destination of the tour. Around 12:30PM we started from Jaigad and headed towards Mumbai via Khandala & Neuli Phata.

We reached mumbai at 9:30 PM after having dinner at Penn.