With the information given, it implies there is no relationship between Award
and Employee
.
If that is the case you could create a Custom Data Source to handle this for you. For the sake of completeness I am going to include a stubbed out Award, and Employee class along with a custom Data Source called MixedDataSource. (There is going to be a lot code listed here, but stick with me for a second).
Award.java
package test;
public class Award {
private String shortName;
private String description;
public Award(String shortName, String description) {
super();
this.shortName = shortName;
this.description = description;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Employee.java
package test;
public class Employee {
private String name;
private String position;
public Employee(String name, String position) {
super();
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
MixedDataSource.java
package test;
import java.util.List;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
@SuppressWarnings("rawtypes")//have to add this because we are not using generics
public class MixedDataSource implements JRDataSource {
private List rows;
private int index=0;
public MixedDataSource(List rows) {
super();
this.rows = rows;
}
@Override
public Object getFieldValue(JRField arg0) throws JRException {
Object obj = rows.get(index);
if (obj instanceof Award){
Award row = (Award)obj;
//now get the field name
if (arg0.getName().equals("shortName")){
return row.getShortName();
} else if(arg0.getName().equals("description")){
return row.getDescription();
}
} else if (obj instanceof Employee){
Employee row = (Employee)obj;
if (arg0.getName().equals("name")){
return row.getName();
} else if(arg0.getName().equals("position")){
return row.getPosition();
}
}
//means we don't know what to do with it, so just return null
return null;
}
@Override
public boolean next() throws JRException {
//This method is used by jasper to tell us they are moving to the next row.
//So increment the index and return true if there are still more rows, if not
//return false
index = index+1;
if(index < rows.size()){
return true;
}
return false;
}
}
This would work, but probably not the way you want. My assumption is that there is a relationship between an Award and Employee and you are wanting to do some type of grouping and ordering. Essentially you want an Award
and Employee
on the same row. You may want to group by Award and list the Employees. You may want to do the opposite and group by Employee and list Awards. If that is the case, ignore all that above, it is useless.
What you really need to do is create a new bean (we could call it EmployeeAward
) with the information you have. This could be really easy, if you are using a sql query to do this, or may require a little more work if you are using something like hibernate. where you are essentially just saying give all the Awards and it gives you a list. If you are doing the latter, it will probably be easier to step down to SQL or HSQL(I think that what they call it) and write the query by hand.
So create a class called EmployeeAward
. Here is mine:
package test;
public class EmployeeAward {
private String employeeName;
private String employeePosition;
private String shortName;
private String description;
public EmployeeAward(String employeeName, String employeePosition,
String shortName, String description) {
super();
this.employeeName = employeeName;
this.employeePosition = employeePosition;
this.shortName = shortName;
this.description = description;
}
public EmployeeAward(Employee employee, Award award) {
super();
this.employeeName = employee.getName();
this.employeePosition = employee.getPosition();
this.shortName = award.getShortName();
this.description = award.getDescription();
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public String getEmployeePosition() {
return employeePosition;
}
public void setEmployeePosition(String employeePosition) {
this.employeePosition = employeePosition;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Now by whatever means you have create your list of these object so you have a List<EmployeeAward> emplyeeAwards
instantiated in there. Each item in this list is going to be a row in your report. Now here is the nice part, create your dataSource:
JRDataSource datasource = new JRBeanCollectionDataSource(employeeAwards);
Then pass that on like normal and your work is done.
In closing, I would like to say you can do a lot of cool things with JasperReports, but what I see a lot of folks doing is making it more complicated than it needs to be. You will find that JasperReports like what I call flat datasources (i.e. same objects in list, each item in list is a row, etc). If you do that, life becomes easier and more enjoyable.