Pages

Sunday, September 18, 2011

How to change SVN user in eclipse

When we connect to a SVN repository, we should provide username and password. Most of the time, We have used to set these credentials saved in a particular computer to prevent prompting for these credentials for subsequent synchronization with repository every time. Then for every workspace, eclipse will get these as SVN credential with out asking from us.

How can we reset these credentials to a another user account?

Go to this location in your computer file system.

C:\Documents and Settings\<User>\Application Data\Subversion\auth\svn.simple

Delete the file inside "svn.simple" folder, restart the eclipse and try to synchronize with repository again. You will be prompted for user name and password which was missing for long time in your computer.

I will update for linux soon. 

Sunday, September 11, 2011

How to Use Hibernate for Composite Ids with association mappings

Recently, We faced a tricky situation with hibernate association mapping with a composite id field. We needed to have bidirectional association with one-to-may and many-to-one.Our tow tables was "REPORT" and "REPORT_SUMMARY" which has one-to-many relationship from REPORT to REPORT_SUMMARY and many-to-one relationship from REPORT_SUMMARY to REPORT table. The primary key of REPORT_SUMMARY table is defined as a composite primary key which consists of auto increment id field and the primary key of REPORT table.
CREATE TABLE REPORT (
     ID INT(10) NOT NULL AUTO_INCREMENT,
     NAME VARCHAR(45) NOT NULL,
     PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE REPORT_SUMMARY (
   ID INT(10) NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(45) NOT NULL,
   RPT_ID INT(10) NOT NULL,
   PRIMARY KEY (`ID`,`RPT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

The hibernate entity classes are as fallows.

Report.java
package com.semika.autoac.entities;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Report implements Serializable{

    private static final long serialVersionUID = 9146156921169669644L;

    private Integer id;
    private String name;
    private Set<ReportSummary> reportSummaryList  = new HashSet<ReportSummary>();
    
    public Integer getId() {
         return id;
    }
    public void setId(Integer id) {
         this.id = id;
    }
    public String getName() {
         return name;
    }
    public void setName(String name) {
         this.name = name;
    }
    public Set<ReportSummary> getReportSummaryList() {
         return reportSummaryList;
    }
    public void setReportSummaryList(Set<ReportSummary> reportSummaryList) {
         this.reportSummaryList = reportSummaryList;
    }
}

ReportSummary.java
package com.semika.autoac.entities;

import java.io.Serializable;
public class ReportSummary implements Serializable {

private static final long serialVersionUID = 8052962961003467437L;

private ReportSummaryId id;
private String name;

public ReportSummaryId getId() {
    return id;
}
public void setId(ReportSummaryId id) {
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    ReportSummary other = (ReportSummary) obj;
    if (id == null) {
       if (other.id != null)
          return false;
       } else if (!id.equals(other.id))
          return false;
    if (name == null) {
       if (other.name != null)
          return false;
       } else if (!name.equals(other.name))
          return false;

   return true;
  }
}

ReportSummaryId.java
package com.semika.autoac.entities;

import java.io.Serializable;

public class ReportSummaryId implements Serializable{

private static final long serialVersionUID = 6911616314813390449L;

private Integer id;
private Report report;

public Integer getId() {
   return id;
}
public void setId(Integer id) {
   this.id = id;
}
public Report getReport() {
   return report;
}
public void setReport(Report report) {
   this.report = report;
}
@Override
public int hashCode() {
   final int prime = 31;
   int result = 1;
   result = prime * result + ((id == null) ? 0 : id.hashCode());
   result = prime * result + ((report == null) ? 0 : report.hashCode());
   return result;
}
@Override
public boolean equals(Object obj) {
   if (this == obj)
      return true;
   if (obj == null)
      return false;
   if (getClass() != obj.getClass())
      return false;
   ReportSummaryId other = (ReportSummaryId) obj;
   if (id == null) {
      if (other.id != null)
         return false;
      } else if (!id.equals(other.id))
         return false;
   if (report == null) {
      if (other.report != null)
         return false;
      } else if (!report.equals(other.report))
         return false;

   return true;
  }
}
Report object has a collection of ReportSummary objects and ReportSummaryId has a reference to Report object. The most important part of this implementation is hibernate mapping files.
Report.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.semika.autoac.entities.Report" table="REPORT" >
         <id name="id" type="int" column="id" >
                 <generator class="native"/>
         </id>
         <property name="name">
               <column name="NAME" />
         </property>
         <set name="reportSummaryList" table="REPORT_SUMMARY" cascade="all" inverse="true">
             <key column="RPT_ID" not-null="true"></key>
             <one-to-many class="com.semika.autoac.entities.ReportSummary"/>
         </set>
     </class>
</hibernate-mapping>
ReportSummary.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.semika.autoac.entities.ReportSummary" table="REPORT_SUMMARY" >
        <composite-id name="id" class="com.semika.autoac.entities.ReportSummaryId">
             <key-property name="id" column="ID"></key-property>
             <key-many-to-one name="report" 
                              class="com.semika.autoac.entities.Report"
                              column="RPT_ID"</key-many-to-one>
        </composite-id>
        <property name="name">
             <column name="NAME" />
        </property>
    </class>
</hibernate-mapping>

Saturday, July 2, 2011

How to delete child elements in Parent/Child relationship - JPA

Orphans are the elements removed from a child collection in a parent/child relation ship. If You expect the deletions of child records from the database with by removing child elements from the child collection or with the deletion of parent record in a parent/child relationship with javax.persistence.CascadeType.All , it will not delete the child records from the database. But simple value typed child elements like a collection of strings, will be removed with the removal of parent object or with removal of elements from the child collection. When the parent is saved, the value-typed child objects are saved as well, when the parent is deleted, the children will be deleted. 

If the child objects being entities, not value-types, those have their own life cycle, like "Items" in a "Order". For this kind of scenario, If You want to delete child records from the database with the removal of child elements from the child collection or with the deletion of parent record, you will have to use
org.hibernate.annotations.CascadeType.DELETE_ORPHAN

public class Department {

    @OneToMany(cascade = {javax.persistence.CascadeType.ALL})
    List<Location> locations;

    @OneToMany(cascade = {CascadeType.ALL})
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)   
    List<Employee> employees;
}


Since "Location" is a simple value typed objects, javax.persistence.CascadeType.ALL will perfectly work when deleting orphans. But "Employee" is not a simple value typed objects. So We have to use hibernate's @Cascade annotation with value org.hibernate.annotations.CascadeType.DELETE_ORPHAN in order to remove orphans with removal of parent.

  • It doesn't usually make sense to enable cascade on a <many-to-one> or <many-to-many> association. Cascade is often useful for <one-to-one> and <one-to-many> associations.
  • If the child object's lifespan is bounded by the lifespan of the of the parent object make it a lifecycle object by specifying cascade="all,delete-orphan"

Friday, October 22, 2010

Struts2 exception flow interceptor

The purpose of this post is to explain, How we can use struts 2 interceptor to bring exception messages into the view screen of your web application and be aware the user about those in meaning full way. There may be several ways of implementing this kind of functionality. My major purpose of this technique is to keep developer significantly free for taking exception messages to the view screen, and let the interceptor to do this instead, once We have added this feature into our system.

This is very straight forward method. Each struts 2 action is invoked from a interceptor's intercept method and catch the exception with in intercept method and send the message to the view. I am going to explain this technique for struts 2 action invocation via AJAX request. I named the interceptor as ExceptionFlowInterceptor. Let's see, How configure the interceptor in
struts.xml file.

<package name="autoac" extends="struts-default json-default" namespace="/secure">
<interceptors>
     <interceptor name="exceptionFlowInterceptor" class="com.semika.autoac.web.interceptors.ExceptionFlowInterceptor"></interceptor>
     <interceptor-stack name="autoac-stack">
           <interceptor-ref name="exceptionFlowInterceptor"></interceptor-ref
           <interceptor-ref name="defaultStack"></interceptor-ref>
     </interceptor-stack>
</interceptors>

<default-interceptor-ref name="autoac-stack"></default-interceptor-ref>

</package>

Better to give little explanation about the above configuration. I have declared a package called "autoac" which extends struts-default and json-default packages. Since I want to invoke actions in autoac package with ajax request, I have extended autoac package from json-default package. To know further about that, please read about struts 2 json plugin.

I have configured the interceptor so that each action in /secure name space is undergone interceptor's pre-processing and post processing.

Next, We will see the code for our interceptor. I am not going to put the whole source here. I just put, How intercept method behaves.

@Override
public String intercept(ActionInvocation invocation) throws Exception {
   String result = null;
   try{
       result = invocation.invoke();
   } catch(Exception e) {
       ValueStack vs = invocation.getStack();
       if (e.getMessage() == null) {
          vs.setValue("errorMessage", "Internal system faliure.Please contact system administrator.");
       } else {
          vs.setValue("errorMessage", e.getMessage());
       }
       vs.setValue("status", "fail");
       result = "json";
 }

 return result;
}


I guess, You have already got the point. I have invoked the action from intercept method and within in try catch block. Any of the exceptions raised after the action invocation, will be caught here. In case of an exception, You can catch the exception and send it into the view in nice way. In my case, I am handling status field at action's model and update that field accordingly. That is up to you to handle this point.

I have obtained the value stack and update the status field as an error. Struts 2 json plugin serializes the whole action and resulting json object which can be accessed with Javascript.

Thursday, October 14, 2010

CSS extend

This is very simple thing that we do not care too much. When we write CSS file, have you knew that, we can extend CSS attributes from one CSS class to a another CSS class. I will explain this using a very simple example.

Suppose you want to have some customized border styles for cells of a table. For some table cells You need only the top border only, and some other cell You need only the top and bottom border only. For this kind of scenario's, We can use CSS extends feature rather adding repeated CSS attributes.

This is the CSS class for table border top.
.border-top {
        border-top: 1px solid #CCCCCC;
}

Next, You want to have another CSS class for table cells with top and bottom border. If You do not consider about CSS extends, You have to write a CSS class as fallows.
border-top-bottom {
      border-top:1px solid #CCCCCC
      border-bottom:1px solid #CCCCCC;
}

You can see, You have repeatedly added "border-top: 1px solid #CCCCCC;" line for top-bottom CSS class as well. If you extends 'border-top-bottom' CSS class from 'border-top' CSS class, You do not need to do so.

Now I am going to modify 'border-top' CSS class as fallows.
.border-top,  .border-top-bottom {
      border-top: 1px solid #CCCCCC;
}

The above CSS class declarations simply says that, 'border-top-bottom' CSS class inherits all the CSS attributes from 'border-top' CSS class. Then You can write 'border-top-bottom' CSS class as fallows.
.border-top-bottom {
      border-bottom: 1px solid #CCCCCC;
}

You do not need to add 'border-top: 1px solid #CCCCCC;' attribute repeatedly. Further if You want to write CSS class for table cells with border top and right, You can modify 'border-top' CSS class as fallows.
.border-top, .border-top-bottom  .border-top-right{
     border-top: 1px solid #CCCCCC;
}

See carefully, I have added a comma after 'border-top' CSS class and not after 'border-top-bottom'. The above CSS declaration says that, 'border-top-bottom' and 'border-top-right' both CSS classes inherits CSS attributes from 'border-top' CSS class.
Share

Widgets