Friday, December 20, 2013

Writing a simple tomcat valve and listener

Tomcat valves act as  preprocessors of each request for webapps. If we want to hook up our custom processing logic for requests, we can write a valve and register it globally for all webapps or locally for a webapp. 

To register it locally for a webapp, in the Context.xml of the webapp register it as;

 <Valve className="org.test.valve.MessageRecoveryTomcatValve"/>

To define the valve  globally, register it in the catalina-server.xml file

< Engine>
      <Valve className="org.test.valve.MessageRecoveryTomcatValve"/>

Tomcat listeners get notifications when there is any lifecycle state change occurs in a webapp.

This can be registered in the Context.xml of the webapp.

<Listener className="org.test.MyListener" context="GenericJavaBeanResource"/>

Saturday, December 14, 2013

The Desert Flower ! - Waris

A Somalian girl's  incredible journey.

I just pray that one day no woman will have to experience this pain and that it becomes a thing of the past. That's what I'm working toward. -Waris

Some stories are too terrible to tell, but happen. Waris tells her story  to Marie Claire,  reporter- fashion magazine. 

 Could not simply say hats off to Waris. Story tells the truth of the painful lifes of the Somalian women. Terribly speechless !!! 

Tuesday, December 3, 2013

Everlasting songs..

Stress relieve music..

Thursday, November 28, 2013

Get WSDL service address with WSDL4J

Just a short code snippet to show how one may access service, port, address elements from a WSDL definition by using WSDL4J.

Wednesday, November 20, 2013

Rollback Recovery for Non-Deterministic failed events for web services hosted in Axis2

Rollback techniques in message passing systems have been one of the primary areas in message recovering techniques.One significant area where Rollback recovery has played a crucial role is in the area of web services. Web services are now most popular and widely used mechanism in enterprise business, telecommunication, banking world.In many cases, catastrophic failure is a result of network failures,transport errors and web services are down. If we consider underlying transport is stable and server is stable, we could consider the failures in mainly two categories,which are Deterministic failures and Non-deterministic failures. Recovering from Deterministic failures are much more simpler than Non-deterministic events, since services are aware about the errors. But recovering from Non-deterministic events failure is a challenging part, because it is non determined event failure to the service point of view.
                   System downtime  makes loss to an Enterprise and causes other organizational issues. Over the years, there has been a great amount of effort to improve the recovery techniques in messaging systems. With the increase of recovery techniques, IT systems are able to reduce the cost which occurs due to system errors. Failures due to downtime or incorrect results in an end to end system might have considerable monetary penalties. Failures can occur in several levels and can be categorized in different aspects. For example, client side failures, server side failures, transport level failures, processing time errors
                    From the service level, we could categorize the failures based on two factors, which are known failures to that service and unknown failures to that service. Further we could say, that known failures occur when the service sending out messages. Those can be called as Deterministic events for that service. Unknown failures can occur when the service receives requests and that particular service is not in a state to process those requests. Service is not aware, when the request will be arrived. So, if the service is down when client sends request, service won't be able to receive them. Such errors are called Non-deterministic errors to that service.
                   In case of failures, web services can track , recover failures from Deterministic events easily, since those failures are known to web services. Because, in the Deterministic event errors, service is up and running. But when a failure occurs in Non-deterministic events, web services can not track them or unaware about those failures. Such Non-deterministic errors occur when service is down. That is, when service is not up and running, service can not receive requests. So, those requests will be lost. In this case, we make an assumption that, requests are lost because of the service failure.Those failure events are currently omitted under category , such ,”Requests made to the service within the period of service down time”
                For Non-deterministic events, we can apply the Rollback recovery techniques to Rollback the system/service to a consistent state and can replay the failed events. In case of Non-deterministic events, if we can record all Non-deterministic events happen to a web service we can recreate lost state by replaying those events from a known initial condition. The reconstructed consistent state is not necessarily one that has occurred before the failure. It is sufficient that the reconstructed state be one that could have occurred before the failure in a failure-free, correct execution, provided that it be consistent with the interactions that the system had with the outside world.[1]
                       As a solution for Rollback-Recovery for Non-deterministic events failure in web services hosted in Axis2 , Log-based recovery mechanism contains more advantages than Check-point based recovery technique.

Figure:In a failure situation how log based system performs

Assumptions are, 

  • All Non-deterministic events can be identified and their determinants logged to stable storage 
  • Failures occur after the messages are logged to the stable storage. 
  • Underlying transport channel is reliable. 
  • No orphan processes.
  • Assuming single service domain. 
  • There is no inter process connection in the incoming messages. 
  • Server is reliable. 

A proof of concept design for adding "Log based Roll back Recovery" for Non-deterministic failed events in Axis2.:

           The determinant of each Non-deterministic event is needed to log to a stable storage before the event is allowed to affect the computation. An axis2 message log handler is kept at the Inflow of the message. When clients sends request to a service, before service receive those  requests, this handler receives them and log them to the a stable storage(database). All these incoming requests are non-deterministic events for services, which are hosted in a server.
             At initial phase, all incoming requests are logged to the database. At that time , system does not aware about which will be the success message and which will be the failed message. To differentiate both message another Axis2 handler is placed at the outflow of the Message and identified the Non-deterministic failed events .
         When the service becomes to Active state from InActive state, the Observer Process has to monitor it and needs to check the database for any non-deterministic failure messages for that particular service and replay them. If failed requests are found in the database, those are replayed to the service. To replay the failed Non-deterministic events to service, a Serviceclient is used. The service client will construct message payload back from the saved message and service, operation details are set to the message. Using Service client the failed Non-deterministic message can be replayed back to the service successfully.

[1] E.N. Elnozahy, Lorenzo Alvisi , Yi-Min Wng , David B. Johnson “A Survey of Rollback-
Recovery Protocols in Message-Passing Systems” ACM Computing Surveys (CSUR) ,Vol.
34, Issue 3,pp. 375-408 , sept 2002

Thursday, November 7, 2013

Send back a custom error response in Axis2Handler

In some cases, user wants to send back a custom response to client and may want to abort the message flow for some error scenarios. This can be done in a handler, which can be kept at in/out flow.

 In a messageprocess handler, if an exception occurs and if you want to endup the message flow and send back a custom message to client, use "AxisEngine.sendFault(messageContext)".
If we try to set up fault message in the MessageContext as soap body, then we need to set quite number of parameters to send back that message to "to" address...

public class MessageProcessorHandler extends AbstractHandler {
    public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {

       catch (MessageFaultException e) { 
           String faultPayload = getFaultPayload(); //get a fault message
           MessageContext faultContext = getFaultMessagecontext(msgContext,faultPayload);
       return   InvocationResponse.ABORT;
 return InvocationResponse.CONTINUE;

Thursday, October 31, 2013

Adding simple Axis2 Listener/Observer to monitor services

To monitor  hosted service statuses, register a listener in the axis2.xml.  The listener should implement  the "AxisObserver". Currently four statuses can be monitored ;

  • Services
    • Start
    • Stop
    • Deploy
    • Undeploy
  • Modules
    • Engage
    • Disengage
    • Deploy
    • Undeploy
package org.test.axisobserver;
import java.util.ArrayList;

import org.apache.axis2.AxisFault;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.AxisEvent;
import org.apache.axis2.engine.AxisObserver;

 * Axis observer to get notification of service activate/deactiavte/deploy/undeploy operations
public class ServiceMonitorObserver implements AxisObserver {

    public void init(AxisConfiguration arg0) {

     public void serviceUpdate(AxisEvent event, AxisService axisService) {
//if service is activated 
if(AxisEvent.SERVICE_START == event.getEventType()){
//do your stuff
      //if service is deployed
       if(AxisEvent.SERVICE_DEPLOY == event.getEventType()){
//do your stuff

public void addParameter(Parameter arg0) throws AxisFault {

public void deserializeParameters(OMElement arg0) throws AxisFault {

public Parameter getParameter(String arg0) {
return null;

public ArrayList getParameters() {
return null;

public boolean isParameterLocked(String arg0) {
return false;

public void removeParameter(Parameter arg0) throws AxisFault {

public void moduleUpdate(AxisEvent arg0, AxisModule arg1) {

public void serviceGroupUpdate(AxisEvent arg0, AxisServiceGroup arg1) {

The above listener can be registered in the axis2 configuration (axis2.xml) as follows;

 <listener class="org.test.axisobserver.ServiceMonitorObserver"/>

Friday, October 18, 2013

Everlasting songs..

Stress relieve music..

Saturday, September 14, 2013

Content-Type Header and Axis2

I see some issues when set the "Content-Type" Header  in synapse. Aixs2 doesn't obey the "Content-Type" header, when the message conatins  different messageType.

Before sending a soap message to an endpoint in synapse, if we set the "Content-Type" as text/plain, axis2 sends out  the message with text/xml content-type. But if we set messageType property as text/plain, then content-type header of the outgoing message is set to "text/plain".  This is bit confusing as in the documentation, i find that, "messageType" property is used to select correct MessageFormatter.
There are three properties ,that are related to message-type,content-type which can be set in aixs2/transport scopes.

As in the documentations,
<property name="messageType" value="text/plain" scope="axis2" type="STRING"/>
can be used to select right Messageformatter.

<property name="ContentType" value="text/plain" scope="axis2" type="STRING"/>
can be used to select right MessageBuilders

To set the Content-Type transport header,we can use following property.
 <property name="Content-Type" value="text/plain" scope="transport" type="STRING"/>

But the issue is,
When i do following setting in synapse, aixs2 sends out the message with text/xml content-type.

      <property name="Content-Type" value="text/plain" scope="transport" type="STRING"/>
                   <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>

After setting the "messageType" property only i see the correct content-type is set.

Thursday, September 5, 2013

HTTP Basic Auth and WS-Security username/password authentication

Basic-auth and ws-security username/password authentication both are different and independent.

Basic auth is used in HTTP where user name and password will be encoded and passed  with the request as a HTTP header.
Eg:  HTTP header block will have " Authorization: Basic YWRtaW46YWRtaW4="  header element.

Username and password will be  encoded using base64 and which is used in  authorization header.
Eg: base64(username:password) --> base64(admin:admin)

Most of the webservice clients have option to provide basic auth header. In SOAPUI, at "Authentication" tab, we can provide username and password. If we switch to "Raw" format of the request, all the HTTP headers are visible and we can see the Basic Auth header is set.
When we use Basic Auth, the username and password setting is on the HTTP headers. Not in the SOAP message. SOAP message goes with HTTP body.

We can secure webservices using ws-security username/password authentication mechanism that is a simple mechanism to secure services. It enforces user to provide UsernameToken security header in the SOAP requests.

Sample request:

<soapenv:Envelope xmlns:soapenv="" xmlns:ser="http://services.samples">
      <wsse:Security xmlns:wsse="">
      <wsu:Timestamp xmlns:wsu="" wsu:Id="Timestamp-10">
     <wsse:UsernameToken xmlns:wsu="" wsu:Id="UsernameToken-9">
       <wsse:Password Type=""&gtadmin</wsse:Password>

If we check above sample request, the ws-security header is set as part of SOAP message.

WSO2  service hosting servers provide ws-username token security option. If we secure a service using user name token option, (that is, ws-security username/password authentication) we should pass ws-security headers as mentioned above.

But there is POXSecurity handler is available in the platform which converts HTTP-Basic Auth header to ws-security usernametoken header. So, if we enable UserName token security option for a service , we can send HTTP_basic auth header to execute the service.

Or else, we have to send request, with ws-security headers as mentioned in above sample request.

Saturday, August 24, 2013

Extracting HTTP level information in Axis2

From the Aixs2MessageContext, we can get the HttpServletRequest object, which contains HTTP request header information,session details, cookies etc..


public class MessageStoreHandler extends AbstractHandler {

public InvocationResponse invoke(MessageContext msgcontext) throws AxisFault {
             return InvocationResponse.CONTINUE;

       private void  extractHTTPInfo(MessageContext msgContext) {

HttpServletRequest obj = (HttpServletRequest)msgContext .
if (obj != null) {
System.out.println("Method :"+ obj.getMethod());
System.out.println("Content-type :" +obj.getContentType());
System.out.println("Content-length :"+obj.getContentLength());
System.out.println("Remote addtress"+obj.getSession().getLastAccessedTime());

Friday, August 16, 2013

Everlasting songs..

Stress relieve music.

Friday, August 9, 2013

Defining dynamic endpoint in wso2esb

In synapse(/wso2esb), when we define endpoints, we have to provide endpoint URL, which is  most of the time  hard coded. Those endpoint urls can not be changed dynamically at runtime.
But if user likes to send requests to an endpoint which address has to be constructed from incoming request/any other way, we can use Header mediator with Property mediator to achieve this.
For instance, if the End service name has to be picked from the request, we can use property mediator to pick and store the service name. Later use the Header mediator to set "To" header using the property mediator and forward the request to default endpoint.

The sample request is as follows( it contains the service name , which is used to find the endpoint address)

<soapenv:Envelope xmlns:soapenv="" xmlns:ser="http://services.samples" xmlns:xsd="http://services.samples/xsd">
            <xsd:symbol>MSFT </xsd:symbol>  

If we send above request to the "testProxy", which will forward the request to http://localhost:9000/services/SimpleStockQuoteService endpoint, which can be constructed as mentioned above.

testProxy conf:

  <proxy name="testProxy"    transports="https http"
          startOnLoad="true"   trace="disable">
            <property name="server"  value="http://localhost:9000/services/"
                      scope="default"  type="STRING"/>
            <property xmlns:m1="http://services.samples/xsd"
                      name="service"   expression="//m0:getQuote/m0:request/m1:service"
                      scope="default"   type="STRING"/>
            <header xmlns:m1="http://services.samples/xsd"
                    xmlns:m0="http://services.samples"   name="To"

You can use xpath functions in the Header/Property mediator expressions.

Sunday, August 4, 2013

Writing a simple Axis2 handler

If we want to listen all the incoming/outgoing messages coming to/from the service, we can write an axis2 handler which can be placed in a phase, which is executed in order as defined in the axis2 configuration. The phase can contain more than one handler.
Message flow is categorized  as;

  • InFlow
  • OutFlow
  • InFaultFlow
  • OutFaultFlow
As name implies, the message flows indicate the request,response and their fault execution paths. In each flow there are phases defined and we can keep our handler in the right flow and right phase.

Sample code:

package org.test.sample;

import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.context.MessageContext;

public class MessageHandler extends AbstractHandler {
private static final Log log = LogFactory.getLog(MessageHandler.class);

public InvocationResponse invoke(MessageContext msgcontext) throws AxisFault {
if (log.isDebugEnabled()) {
log.debug("Message Store handler is executing");
AxisService axService = msgcontext.getAxisService();
return InvocationResponse.CONTINUE;

The message execution can be continued, aborted or suspended.

Once we created the jar out of this, we need to keep the jar in the classpath(ie:lib folder) and has to register the handler in the axis2 configuration.
We can register the handler programmatically as a module or  we can edit the axis2.xml file based on the requirement.

Editing axis2.xml

Add the following configuration in the suitable flow/phase.
< phaseOrder type="InFlow">
< phase name="Transport">
< handler name="MessageHandler" class="org.test.sample.MessageHandler">
< /phaseOrder>

Programmatically adding the module;


Saturday, July 6, 2013

Life is cheap...

Life is made cheap for  group of people in some countries. It is history..
Death is cheaper and it is proportional..
Eyes with full of painful tears, waiting for years to live!

Wednesday, June 19, 2013

Class Endpoints:Sample

In my older post , I mentioned that Class endpoint(ie: custom endpoints) feature is available in later versions of synapse, which is branched in WSO2 svn location.
Since, there are number of usecases to implement the class endpoint, i thought to write a simple sample using class endpoints.

All message sending logic is handled in the class in synapse core. For instance, if we want to have our custom client which to do its own message sending  logic,we could write this type of endpoints.

In the following sample, i have defined an Custom Class Endpoint(ie:UAddressEndpoint) which extends the Synapse.AbstarctEndpoint class to define its own endpoint logic.

I read a parameter (this parameter ,we provide from endpoint configuration) from registry , where i saved my custom endpoint configuration . From that endpoint configuration i read  all endpoint related parameters, and use that as an Endpoint and have a separate   logic to send out message,

package org.wso2.carbon.endpoint.uep;

import org.apache.axis2.AxisFault;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.endpoints.AbstractEndpoint;
import org.wso2.carbon.endpoint.uep.util.UEndpointUtil;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpoint;

 * ESB specific UAddressEndpoint class,extended from synapse Abstractendpoint.
public class UAddressEndpoint extends AbstractEndpoint {

* The registry location of the uep configuration,where it is stored
* Eg:conf:/repositoryuepTestEP.xml
private String uepConfigurationPath;

private static final Log log = LogFactory.getLog(UAddressEndpoint.class);

public UAddressEndpoint() {


* Getter and Setter of the parameter which we define at the classendpoint
* configuration.
* eg:
* name="uepConfigurationPath">conf:/repositoryuepTestEP.xml

         * @param uepConfiguration
public void setUepConfigurationPath(String uepConfigurationPath) {
this.uepConfigurationPath = uepConfigurationPath;

public String getUepConfigurationPath() {

return uepConfigurationPath;

* Override the AbstractEndpoint.send(). Use the UEP handler to
* get endpoint specific
* Configurations

public void send(MessageContext synMessageContext) {
if (log.isDebugEnabled()) {
log.debug("Executing UAddressEndpoint Sender ");

try {

UAddressEndpointDefinition addressEPDefinition = new UAddressEndpointDefinition();
UEndpointUtil uepUtil = new UEndpointUtil();

UnifiedEndpoint unifiedEndpoint = uepUtil.getUnifiedEndpoint(uepConfigurationPath);

UEndpointAxis2MEPClient.send(unifiedEndpoint, getDefinition(), synMessageContext);
} catch (AxisFault e) {
log.error("Error in executing the message", e);


In the above sample,if you notice that I have my own class(ie: UEndpointAxis2MEPClient) to handle the message sending logic.

If we want to use this type of class endpoint, in synapse configuration we have to define our custom endpoint like this;

<endpoint name="CustomEndpoint">
                    <class name="org.wso2.carbon.endpoint.uep.UAddressEndpoin">
                                 <parameter name="uepConfigurationPath">conf:/repositoryuepTestEP.xml</parameter>

Monday, June 17, 2013

Retrieving Axis2MessageContext from SynapseMessagecontext

Some times, we need to access Axis2 MessageContext in the sequence flow, using a custom class mediator.
Here is how you can access it;

public boolean mediate(MessageContext synapseMessageContext) {

org.apache.axis2.context.MessageContext axis2MsgContext;
axis2MsgContext = ((Axis2MessageContext) synapseMessageContext).getAxis2MessageContext();

Thursday, May 2, 2013

Accessing request MessageContext from response's MessageContext in axis2.

In some cases we need to access the incoming requests' properties/message in the outpath/response path.
For instance; we may need the request message's header information or else we might need the request message  in the response path for  any processing logic.
Request message context can be retrieved like as follows;
MessageContext requestMessageCtx = responseMessageCtx.getOperationContext()
Using the Request's MessageContext we could retrieve header details/message etc..

Tuesday, March 12, 2013

Accessing various information of a message in a mediation flow in WSO2ESB

Property mediator helps us to access various information of a message ,which passes through ESB. Within a sequence , we could use property mediator to get info about a message.
We can assign a value to a property as a string value or using xpath expression. Two actions are defined for property mediator.
  • Set
  • Remove
 <property name="MESSAGE" value="Executing in sequence"/>
 <property xmlns:m=""   name="test"   expression="//m:getQuote/m:symbol"
                   scope="default"  type="STRING"/>

We can use supported xpath functions,such as mathematical/logical operations and other predefined functions can be used to assign values in the property mediator.


<property xmlns:ns="http://org.apache.synapse/xsd"   name="testProp"
                expression="fn:concat('hello','world')"   scope="default"/>

We can use  built in get-property() xpath function to read properties,which are available in the synapse messagecontext.
Eg: If a property "SYSTEM_TIME" available in the synapse message context; 

<property xmlns:ns="http://org.apache.synapse/xsd"   name="systemtime"
                expression="get-property('SYATEM_TIME')"   scope="default"/>

We can use property mediator to set values in different scopes, which can be accessed in those specific scope. There are 4 scopes,which are;
  • synapse/default : This property will be available in both insequence and outsequence.
  • axis2 : This property will be available in the particular sequence. can be retrieved from Axsi2Messagecontext.
  • transport:  This scope is used to set a property in the transport header.
  • axis2-client: Like "axis2" scope, but can be  retrieved form the Axis2Messagecontext.options.

<property name="myProp" value="abc" scope="default" type="STRING"/>
<property name="myProp" value="abc" scope="transport" type="STRING"/>
<property name="myProp" value="abc" scope="axis2" type="STRING"/> 
<property name="myProp" value="abc" scope="axis2-client" type="STRING"/>

When we retrieve properties from a specific scope;
 <property xmlns:ns="http://org.apache.synapse/xsd"    name="remotehost"
                    expression="get-property('axis2', 'REMOTE_HOST')"/>

There are some predefined xpath properties , which we can use directly to retrieve some common properties.
  • $axis2: Used to get the property at the axis2 scope.
 eg :
 <property name="MessageType is" expression="$axis2:messageType"/>
  • $trp: Used to get transport header properties.
 <property name="axis2Prop" expression="$trp:Content-Type"/>
  • $ctx : Used to get synapse scope properties;
 If we have a property named as "myProp" in synapse scope, which can be retrieved in the following manner;
 <property name="testProp" expression="$ctx:myProp"/>
  • $url : Used to retrieve parameters defined in the url
For a request url; http:// localhost:8280/getSimpleQuote?symbol=IBM

<property name="symbol" expression="$url:symbol"/>
The above will retrieve the symbol value; ie:IBM

Tuesday, February 26, 2013

Everlasting songs..

Stress relieve music.

Friday, February 15, 2013

Accessing registry resources from class mediator in wso2esb

In the mediation process, users might need to access the registry resources, which are stored in the governance/config registries in wso2esb.
In the normal sequence flow, we could point the resources as registry keys in the mediators. But if we want to access them in a class mediator, where we may need to do custom process on the resource, we could retrieve the "WSO2Registry" instance from the  "SynapseConfiguration" and from the registry instance we could access different resources which are stored in the different registries.

Likewise if we have a 'LocalEntry' defined in the synapse configuration we could retrieve it from the "LocalRegistry". LocalEntries  are elements, used to declare registry entries that are local to the ESB instance. They are static resources and has high priority than a resource with the same name  hosted in embedded wso2registry.

Here is a sample class mediator, which can be used to retrieve a LocalEntry and resources hosted in governance/config registry.
import org.apache.synapse.MessageContext;
import org.apache.synapse.config.Entry;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.registry.Registry;
public class CustomRegistryRetriveMediator extends AbstractMediator {
    public boolean mediate(MessageContext synapseMsgContext) {

        // if localentry "
testLocalentry" defined in synapse econfig
        Entry localEntryObj = (Entry) synapseMsgContext.getConfiguration()
        System.out.println(" value: " + localEntryObj.getValue());
        System.out.println(" Filename : " + localEntryObj.getFileName());

        // goverance/config registry
        Registry regInstance = synapseMsgContext.getConfiguration()
        Object obj=regInstance.getResource(new Entry("gov:/test1.txt"),null);       
        Object obj2=regInstance.getResource(new Entry("conf:/test2.txt"),null);   
        return true;

Tuesday, January 8, 2013

Still a long journey for women!

During the past few days Delhi/India was in a bit tense situation due to several protests against the gang rape of a college girl. There are numerous comments from various parties , why it happened, who are (what) the reasons and the judgements also provided for the suspects by various parties. At media interviews /political meetings participants have been asked for their views and getting criticism about the comments they made to public.
When all these protests going on, at  the other end there are cruel rapes occur  all over India. Those cruel activities are fail to get most peoples attention rather than a single line of a news in few medias.

In Indian medias there are more than five murders/rapes news each and every day. But none of them made such attention to the public. Murders happen in varieties. Power of imagination is applied on murders, acid attacks,rapes which are not restricted to any of the age limits. Rules and regulations are generated by a group of people in village areas. Punishmants are made by them. Most of these, fail to get more people/media attention, because those people are poor, different cast, politics, race,religion. Not only in India, such cruel attacks against women happen mostly in the Asian countries. Very few get attention, like the attack against kid Malala.

The most populous democracy country, has still a long journey for women rights!