Million thanks! Alien thoughts!

Hi Majrul,

It would not be wrong if i say “I am u r Fan”, i have impressed with your depth knowledge and trainning skill in Java technologies(Reference trainning attended in Mastek Ltd).

Dear Majrul,

I am Big Fan of you after listening to your Hibernate & Spring training this week.

Hi Majrul,

I attended your training course on Spring onsite.  Considering how well the course was structured, conducted along with relevant examples and your in depth knowledge, your name came first to my mind for some requirement.

It’s always been the feedback of my participants that doesn’t allow me to leave this profession 🙂 Many a times people ask me why don’t you get into development or join some company? I hope the answer to this question is very clear 🙂

I thank every one once again for your feedbacks and the motivation, without which i wouldn’t have excelled in this field at all. Sometimes my role models are my participants itself, i get that zeal and energy i need to push myself to my limits.

I am proud to be a Trainer and i will continue training the world as long as i can.

My aim is to teach these Aliens also a bit of Java if i get an opportunity 😉

e432c9681505a4cad6db736dbc019010486cba06

 

.NET Experts, Java Champions!

Yet another unique batch i took recently. Once again the best part was that the participants had little background of Java and more of C++/.NET. So when two different worlds collide, the result is truly adventurous 🙂

Diebold

C++ Headers in a JAR

It feels great when you get to know great people. Thanks a lot for giving me an opportunity! The best thing about this batch was that the participants were from C++ background. So when C++ and Java combines, the result is truly out of the world!

Kaushal, Sunil, Durga, Amit

Hibernate/JPA Performance. Why eager loading hurts?

Introduction

With more and more applications using Hibernate/JPA, the need for understanding the core concepts plays a very important role so as to avoid performance issues later on.

In this blog post, i will share my views on lazy & eager loading/fetching issues. I am still left with proper formatting, so please bear with me for some time if in case you see the content is not properly aligned.

In Hibernate, except for one-to-one, all other forms of associations are lazily loaded. One for one-to-one association, eager loading is used by default in Hibernate. But when using JPA, even for many-to-one association, eager loading is used by default.

Let’s come back to lazy loading for the time being 🙂

With the help of an example, we will discuss the problem in detail. I will use JPA annotations for the sake of simplicity and reduced configuration.

@Entity
@Table(name="TBL_CUSTOMER")
public class Customer {

	@Id
	@GeneratedValue
	private int id;

	private String name;
	private String email;

	@OneToMany(mappedBy="customer")
	private Set<Order> orders;

        //getters and setters	

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", email=" + email
				+ "]";
	}
}
@Entity
@Table(name="TBL_ORDER")
public class Order {

	@Id
	@GeneratedValue
	private int id;

	private Date orderDate;
	private double amount;

	@ManyToOne
	private Customer customer;

        //getters and setters

	@Override
	public String toString() {
		return "Order [id=" + id + ", orderDate=" + orderDate + ", amount="
				+ amount + "]";
	}
}

Now, i am going to add lot’s of customers in the database:

for(int i=1;i<=100;i++) {
	Customer customer = new Customer();
	customer.setName("A"+1);
	customer.setEmail("a"+i+"@gmail.com");
	entityManager.persist(customer);
}

And i am going to place orders for some of these customers:

for(int i=1;i<=100;i++) {
	int anyRandomCustomer = new Random().nextInt(100) + 1; 
        //assumption is that pk assigned when adding customers was in range 1-100
	Customer customer = entityManager.find(Customer.class, anyRandomCustomer);
	Order order = new Order();
	order.setAmount(i*10);
	order.setOrderDate(new Date());
	order.setCustomer(customer);
	entityManager.persist(order);
}

So we have sufficient data in the database to proceed further with.

n+1 problem. What’s the problem?

Hibernate uses lazy loading for all forms of association except one-to-one by default. Which means for one-to-many, many-to-one, many-to-many and others, hibernate will not the parent/child object graph by default.

In context of the example it means, if we load some Customer from the database, Hibernate will not load the orders placed by that customer till not forced to do so.

To understand the problem why many a times developers enable eager loading, let’s run this piece of code to see what happens:

Customer customer = entityManager.find(Customer.class, 1);
entityManager.detach(customer);

System.out.println(customer);
System.out.println(customer.getOrders());

I am using detach method just so that i can demonstrate the lazy loading behaviour. Generally an object becomes a detached object when we close the underlying Session/EntityManager associated with it, so in projects you will not always call this method. Also i’ve overriden toString() method in both the POJOs for getting some readable output. If you run the above code, this is what happens:

Hibernate: /* load Customer */ select customer0_.id as id0_0_, customer0_.email as email0_0_, customer0_.name as name0_0_ from TBL_CUSTOMER customer0_ where customer0_.id=?
Customer [id=1, name=A1, email=a1@gmail.com]
org.hibernate.LazyInitializationException: could not initialize proxy - no Session

So as you can see clearly, Customer got loaded, but Hibernate failed to load the orders placed by that customer, because to do some it requires the object to be in the attached/managed state. For detached objects, there is nothing Hibernate can do by default.

This is where we find developers switching to eager loading. Just because what we want is that when the Customer get’s loaded, the Order placed by that customer also gets loaded. So let’s modify the association to enable eager loading:

@OneToMany(fetch=FetchType.EAGER, mappedBy="customer")
private Set<Order> orders;

Let’s run the previous code again and see what happens now:

Hibernate: /* load Customer */ select customer0_.id as id0_1_, customer0_.email as email0_1_, customer0_.name as name0_1_, orders1_.customer_id as customer4_0_3_, orders1_.id as id1_3_, orders1_.id as id1_0_, orders1_.amount as amount1_0_, orders1_.customer_id as customer4_1_0_, orders1_.orderDate as orderDate1_0_ from TBL_CUSTOMER customer0_ left outer join TBL_ORDER orders1_ on customer0_.id=orders1_.customer_id where customer0_.id=?
Customer [id=63, name=A1, email=a63@gmail.com]
[Order [id=73, orderDate=2013-04-19 19:40:19.273, amount=730.0], Order [id=93, orderDate=2013-04-19 19:40:19.314, amount=930.0], Order [id=78, orderDate=2013-04-19 19:40:19.281, amount=780.0], Order [id=47, orderDate=2013-04-19 19:40:19.201, amount=470.0], Order [id=87, orderDate=2013-04-19 19:40:19.302, amount=870.0]]

Pretty good so far. But the real problem is not visible still. Let’s use the Query or Criteria API to load more than one customer to see what happens. The code we need to run now is:

Query query = entityManager.createQuery("select c from Customer c");
List<Customer> customers = query.getResultList();
for (Customer customer : customers) { 
     System.out.println(customer); 
}

Now in this situation where we are loading multiple parent rows from the database and eager loading enabled for it’s children, let’s see what happens behind the scenes by referring to the hibernate logs:

Hibernate: /* from Customer */ select customer0_.id as id0_, customer0_.email as email0_, customer0_.name as name0_ from TBL_CUSTOMER customer0_
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
Hibernate: /* load one-to-many jpa.onetomanybi.Customer.orders */ select orders0_.customer_id as customer4_0_1_, orders0_.id as id1_1_, orders0_.id as id1_0_, orders0_.amount as amount1_0_, orders0_.customer_id as customer4_1_0_, orders0_.orderDate as orderDate1_0_ from TBL_ORDER orders0_ where orders0_.customer_id=?
...

Actually that’s not the complete log, for those 100 customers that we loaded, Hibernate has fired 100 subsequent select queries to load the orders for each customer one by one. Each customer can have a history of many orders. This is what is referred to as the n+1 problem. Now this happened because we had enabled eager loading. We asked Hibernate that whenever i load a customer, you please go and get me the orders placed by that customer also loaded. Not to blame, it’s not Hibernate’s fault. I have seen people using eager loading in so many projects without thinking about the consequence of it. In my trainings i see to it that my participants are aware of this and they don’t do the same mistake in their projects.

Just imagine what will happen in a live environment where the amount of data will be more than this dummy example and a small mistake of the developer using eager loading, will cause such a huge performance bottle neck.

The question is, do we really need the orders list everytime a customer is loaded? Not really according to me, if we take the power of Query/Criteria API, we don’t have to rely on eager loading at all. With the help of joins, one can do whatever we want. So if a use case arises where we need the Customer and the Order information both, a simple query will solve the problem.

So i suggest that eager loading should only be used if we are 100% sure that the parent/child graph has to be loaded everytime in the application across all the use cases. But i believe this will be a very rare case. Now how will the Query/Criteria code look like to eagerly load the data:

Query query = entityManager.createQuery("select c from Customer c join fetch c.orders");
List<Customer> customers = query.getResultList();

for (Customer customer : customers) {
	System.out.println(customer);
}

I am using fetch keyword, which will solve the above n+1 problem. As of now there is no where condition in the query, but generally we will have some. So what i suggest is that, use lazy loading by default, and whenever there is a use case in which you need both the parent and child, a simple query will get the job done.

 

Performance in Hibernate/JPA. Should we cascade or not?

Introduction

When using any framework, it’s so important that the performance of an application is not hampered by using it and the same is true for Hibernate as well. When using Hibernate in projects, I have seen developers doing some common mistakes and that results in Hibernate performing very badly. Now, that’s not Hibernate’s fault by any means.

In this post, I am going to discuss about the need for cascade when setting up associations, and at the same time we discuss about the performance impact as well.

What is cascade?

In this example of a cycle stand:

cycles

If i push one of the cycles, all the cycles will fall. Why? Because that’s what we call it as the cascading effect. It’s like a chain of cycles and if one in the chain falls, everyone does. Exactly the same concept is used in Hibernate for associations. As such cascade is not any ORM specific term, you will find the usage of cascade in the RDBMS world as well in the form of cascade delete commonly. Hibernate adds a broader meaning to the term cascade and it is very helpful in setting up of associations.

In this post, i will not discuss about each and every cascade option, rather the focus is on whether should we use it or not?

Example

We will take a small example and what better example than a Department/Employee association to go ahead with.

public class Department {

	private int deptno;
	private String name;
	private String location;
	private Set<Employee> employees;

        ... getters and setters ...

}
public class Employee {

	private int empno;
	private String name;
	private double salary;
	private Department dept;

        ... getters and setters ...

}

For one-to-many and many-to-many associations, we need some collection, Java offers us with List, Set and Map. The commonly used ones in Hibernate are List and Set. When to use List and when to use Set? Well, i would like to answer this question in bits and pieces. So let’s start with a Set initially and what will happen if we use a List instead, we will discuss that later on.

Now we need to do the mapping of the above entities to the tables in the database. I will be using JPA annotations, which means we can test the issues that i will be discussing with other ORMs as well.

This is how our entities look like after applying the required annotations:

@Entity
public class Department {

	@Id
	private int deptno;

	private String name;
	private String location;

	@OneToMany(mappedBy="department")
	private Set<Employee> employees;

        ... getters and setters ...
}
@Entity
public class Employee {

	@Id
	private int empno;

	private String name;
	private double salary;

	@ManyToOne
	@JoinColumn(name="deptno")
	private Department department;

        ... getters and setters ...
}

Test Case 1: Adding a Department

Department is the parent entity, so let’s go and add atleast one Department.

Department department = new Department();
department.setDeptno(10);
department.setName("Admin");
department.setLocation("Mumbai");

entityManager.persist(department);

Test Case 2: Adding Employees

Now this is where the list of problems that we need to discuss with begins. Let’s have a look at one possible way of doing this.

Department department = entityManager.find(Department.class, 10);
entityManager.detach(department);

Employee employee1 = new Employee();
employee1.setEmpno(1001);
employee1.setName("Majrul");
employee1.setSalary(1000);

Employee employee2 = new Employee();
employee2.setEmpno(1002);
employee2.setName("Zubair");
employee2.setSalary(2000);

department.getEmployees().add(employee1);
department.getEmployees().add(employee2);

entityManager.merge(department);

As it should be clear, what we are trying to do is, navigate from parent to child in the above code. I am using detach method just so that i can demonstrate the lazy behaviour also. Because of lazy loading, what will happen is when the Department object get’s created, the employees associated with that department will not get loaded by default. Generally an object becomes a detached object when we close the underlying Session/EntityManager associated with it, so in projects you will not always call this method.

Let’s run the above code and see what happens. The problem is that it doesn’t work, it fails with this error:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

The culprit in above code is:

department.getEmployees().add(employee1);
department.getEmployees().add(employee2);

Without loading the collection, Hibernate won’t allow any operation to be performed on it. Now to fix the error, one has to switch to eager loading. So let’s go and change the mapping that we did in Department class for the employees collection with eager loading enabled:

@OneToMany(fetch=FetchType.EAGER, mappedBy="department")
private Set<Employee> employees;

I won’t recommend that you use the above eager loading option in projects please, the reason for the same, i will discuss it in a separate post. Now after this change, let’s see what happens if we run the previous code again. It’s still not working, the error this time is:

javax.persistence.EntityNotFoundException: Unable to find Employee with id 1002

Let’s take help from the Hibernate log to understand the problem:

Hibernate: /* load Department */ select department0_.deptno as deptno0_1_, department0_.location as location0_1_, department0_.name as name0_1_, employees1_.deptno as deptno0_3_, employees1_.empno as empno1_3_, employees1_.empno as empno1_0_, employees1_.deptno as deptno1_0_, employees1_.name as name1_0_, employees1_.salary as salary1_0_ from Department department0_ left outer join Employee employees1_ on department0_.deptno=employees1_.deptno where department0_.deptno=?
Hibernate: /* load Department */ select department0_.deptno as deptno0_0_, department0_.location as location0_0_, department0_.name as name0_0_ from Department department0_ where department0_.deptno=?
Hibernate: /* load one-to-many Department.employees */ select employees0_.deptno as deptno0_1_, employees0_.empno as empno1_1_, employees0_.empno as empno1_0_, employees0_.deptno as deptno1_0_, employees0_.name as name1_0_, employees0_.salary as salary1_0_ from Employee employees0_ where employees0_.deptno=?
Hibernate: /* load Employee */ select employee0_.empno as empno1_1_, employee0_.deptno as deptno1_1_, employee0_.name as name1_1_, employee0_.salary as salary1_1_, department1_.deptno as deptno0_0_, department1_.location as location0_0_, department1_.name as name0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.deptno=department1_.deptno where employee0_.empno=?

Well, whatever is going on, it’s not good. Just to add few employees in the database, if Hibernate has to take so much of efforts, what will be the situation in a live case study, not acceptable at all. Let’s understand what’s going on:

  1. Because we enabled eager loading, the first select query is not only loading the Department, but it also loads all the employees associated with that department by performing an outer join.
  2. The remaining select queries, they all get executed when i reattach the Department object with the EntityManager by calling the merge method. merge method needs to decide whether an insert has to performed or an update, so to help him in taking the decision,
    1. merge method fires a select query to check if there is already a row in the database which matches this Department’s deptno.
    2. Not only it fires a select query to check the state of the Department object, it does it even for the employees loaded for that department. So another select query get’s fired for loading all the employees for the current department.
    3. Now for the newly added employees in the set, it has to do the same thing. Another select query is fired to check if there is an Employee with 1001/1002 as empno to decide if an insert will be required or an update.

Now the error thrown by Hibernate is perfect, because there is no employee with empno 1001/1002. But then merge method should have generated the insert query for the new employees, but it didn’t, why? The reason is it needs permission to do so. And this is where cascade attribute comes into play. Hibernate will not cascade any operation that is performed on the parent to it’s child by default, we need to enable it. So let’s go and do one more change in the department/employees association:

@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.MERGE, mappedBy="department")
private Set<Employee> employees;

What are we doing now? All what we are doing now is telling Hibernate that if we call merge method on the Department object, please cascade the merge operation on each employee in the set. So now let’s run the previous code again to see what happens.

Finally, we got it. We managed to add new employees in the database, and this is what Hibernate did for us:

Hibernate: /* load Department */ select department0_.deptno as deptno0_1_, department0_.location as location0_1_, department0_.name as name0_1_, employees1_.deptno as deptno0_3_, employees1_.empno as empno1_3_, employees1_.empno as empno1_0_, employees1_.deptno as deptno1_0_, employees1_.name as name1_0_, employees1_.salary as salary1_0_ from Department department0_ left outer join Employee employees1_ on department0_.deptno=employees1_.deptno where department0_.deptno=?
Hibernate: /* load Department */ select department0_.deptno as deptno0_1_, department0_.location as location0_1_, department0_.name as name0_1_, employees1_.deptno as deptno0_3_, employees1_.empno as empno1_3_, employees1_.empno as empno1_0_, employees1_.deptno as deptno1_0_, employees1_.name as name1_0_, employees1_.salary as salary1_0_ from Department department0_ left outer join Employee employees1_ on department0_.deptno=employees1_.deptno where department0_.deptno=?
Hibernate: /* load Employee */ select employee0_.empno as empno1_0_, employee0_.deptno as deptno1_0_, employee0_.name as name1_0_, employee0_.salary as salary1_0_ from Employee employee0_ where employee0_.empno=?
Hibernate: /* load Employee */ select employee0_.empno as empno1_0_, employee0_.deptno as deptno1_0_, employee0_.name as name1_0_, employee0_.salary as salary1_0_ from Employee employee0_ where employee0_.empno=?
Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)
Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)

My goodness, just to add new children for an existing parent, if the parent has to be loaded with all it’s children, forget it, it’s not acceptable. If you agree with me, all that we want Hibernate to do is this:

Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)
Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)

In my training programs, i stress on cascade property a lot, because i have seen people don’t care about this in their projects. cascade is a wonderful feature because in just one line of code, entityManager.merge(department); the whole Department/Employee graph get’s updated in the database. But the question is do we need this feature of Hibernate always in our project? I think we don’t need this for each and every entity graph in our application.

Let’s redo the adding of employees, but this time we will navigate from child to parent. Before we do that, first let’s go and modify the association and set it back to it’s default.

@OneToMany(mappedBy="department")
private Set<Employee> employees;

And now the test code looks like this:

Department department = entityManager.getReference(Department.class, 10);		
entityManager.detach(department);

Employee employee1 = new Employee();
employee1.setEmpno(1003);
employee1.setName("Ram");
employee1.setSalary(1000);

Employee employee2 = new Employee();
employee2.setEmpno(1004);
employee2.setName("Asif");
employee2.setSalary(2000);

employee1.setDepartment(department);
employee2.setDepartment(department);

entityManager.persist(employee1);
entityManager.persist(employee2);

Let’s run the above code and see how the Hibernate logs look like:

Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)
Hibernate: /* insert Employee */ insert into Employee (deptno, name, salary, empno) values (?, ?, ?, ?)

Voila, we got it what we wanted and that too by a very small change in the approach. Instead of associating the department with it’s employees, we just changed the navigation and associated the employees with their department. To save Hibernate from firing a select query to load the department unnecessarily, i used getReference method instead of find method.

So if we developers write the correct code, we will be able to prevent so many unwanted SQL that get’s generated otherwise. There is no problem in bi-directional associations, the problem is in navigating from parent to child. So i would suggest that the one-to-many end of our associations should be used only for retrieval purpose and for adding/updating/removing the association between the parent and child, we simply don’t touch the parent end, we use the child to take care of it’s relationship with the parent.

Since between List and Set, you will commonly find people using Set, the problems and the solutions we discussed applies to so many use cases in common.

Using List instead of Set

To be continued…

Happy Faces, Serious Work!

Participants of my Hibernate & Spring batch i took at Zycus. Yet another batch full of hard working set of people. You are the ones who make IT shine!

Further update on Public Courses

Hi All,

I am happy to announce that the required arrangement, primarily that means a training room is in place. The training location will be my friend’s computer institute in Bhandup West.

The plan is to initially arrange a session on Spring framework and in the month of March 2013 itself on 30th & 31st. It will be a 2 days course covering the Core Spring framework.

So get your fingers rolling and do let me know your availability and confirmation for the same.

Happy Learning.

Memorable BirthDay

It was a real surprise when the trainees at Mastek Ltd. arranged a surprise cake for me on my birthday on 31st January. The best part was the message embedded on it, and what can i say, i am speechless! Thanks a lot Mastekeers once again for this priceless gift!

Majrul Ansari

Update on Public Courses

Hi,

Based on the input received from people who are interested in attending my sessions, I have identified the following subjects as important ones to begin with:

  1. Spring Framework
  2. Hibernate Framework
  3. Java Performance
  4. EJB 3.0/3.1
  5. WebServices

Please contactme@majrul.com for further details.

Public Courses on Spring and other technologies in Mumbai

Greetings for the new year 20-13 (that’s the way i would like to read it out)!

Off late, i have received lot’s of requests for conducting public courses on subjects that i teach in various corporates and it seems it might be possible very soon. The only reason i don’t do this frequently is because of my continuous some or the other corporate training schedule. So if things work out as per the plan this time, i will announce the public schedule soon. All those who are interested in attending can contactme@majrul.com