I am learning Java as of right now and have just been learned what constructors are. I do not understand why you would need more than one constructor if you need to initialize all variables.
To put it simply, you use multiple constructors for convenience (1st example) or to allow completely different initialization methods or different source types (2nd example.
You might need multiple constructors to implement your class to simply allow omitting some of the parameters that are already setup:
//The functionality of the class is not important, just keep in mind parameters influence it.
class AirConditioner{
enum ConditionerMode{
Automatic, //Default
On,
Off
}
public ConditionerMode Mode; //will be on automatic by default.
public int MinTemperature = 18;
public int MaxTemperature = 20;
public AirConditioner(){ //Default constructor to use default settings or initialize manually.
//Nothing here or set Mode to Automatic.
}
//Mode
public AirConditioner(ConditionerMode mode){ //Setup mode, but leave the rest at default
Mode = mode;
}
//setup everything.
public AirConditioner(ConditionerMode mode, int MinTemp, int MaxTemp){
Mode = mode;
MinTemperature = MinTemp;
MaxTemperature = MaxTemp;
}
}
Another example is when different constructors follow different procedures to initialize the variables.
For instance you could have a data table that simply displays a table of text. The constructor could get the data from either database OR a file:
class DataTable{
public DataTable(){} //Again default one, in case you want to initialize manually
public DataTable(SQLConnection con, SQLCommand command){
//Code to connect to database get the data and fill the table
}
public DataTable(File file){
//Code to read data from a file and fill the table
}
}
A class can have multiple constructors, as long as their signature (the parameters they take) are not the same. You can define as many constructors as you need. When a Java class contains multiple constructors, we say that the constructor is overloaded (comes in multiple versions). This is what constructor overloading means, that a Java class contains multiple constructors.
Having said that, it is completely dependent upon your implementation whether or not you want to create more than one constructor in your class but having more than one constructor can ease your life in many instances. Suppose below class doesn't have a default constructor:
public class Employee {
private int age;
private String name;
Employee(int age, String name){
this.age=age;
this.name=name;
}
}
So, while creating object of this class user would not be able to do so until he has age and name parameters handy which restricts the true functionality of Java objects as Objects' state should be able to be modified and populated at any time once initialized.
Per constructor has specific purpose. Sometimes we need more than one constructor (special in Entity domain case, when use ORM)
For example:
Empty constructor (no arguments) for reflection,
Constructor has argument(s) for create new instance (A a = new A('foo', 'bar');).
These're overload method(s).
Reality example:
package sagan.blog;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.Type;
import org.springframework.util.StringUtils;
import sagan.team.MemberProfile;
import javax.persistence.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* JPA Entity representing an individual blog post.
*/
#Entity
#SuppressWarnings("serial")
public class Post {
private static final SimpleDateFormat SLUG_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(cascade = CascadeType.PERSIST, optional = false)
private MemberProfile author;
#Column(nullable = false)
private String title;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
private PostCategory category;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
private PostFormat format;
#Column(nullable = false)
#Type(type = "text")
private String rawContent;
#Column(nullable = false)
#Type(type = "text")
private String renderedContent;
#Column(nullable = false)
#Type(type = "text")
private String renderedSummary;
#Column(nullable = false)
private Date createdAt = new Date();
#Column(nullable = false)
private boolean draft = true;
#Column(nullable = false)
private boolean broadcast = false;
#Column(nullable = true)
private Date publishAt;
#Column(nullable = true)
private String publicSlug;
#ElementCollection
private Set<String> publicSlugAliases = new HashSet<>();
#SuppressWarnings("unused")
private Post() {
}
public Post(String title, String content, PostCategory category, PostFormat format) {
this.title = title;
this.rawContent = content;
this.category = category;
this.format = format;
}
/* For testing only */
public Post(Long id, String title, String content, PostCategory category, PostFormat format) {
this(title, content, category, format);
this.id = id;
}
public Long getId() {
return id;
}
public MemberProfile getAuthor() {
return author;
}
public void setAuthor(MemberProfile author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public PostCategory getCategory() {
return category;
}
public void setCategory(PostCategory category) {
this.category = category;
}
public PostFormat getFormat() {
return format;
}
public void setFormat(PostFormat format) {
this.format = format;
}
public String getRawContent() {
return rawContent;
}
public void setRawContent(String rawContent) {
this.rawContent = rawContent;
}
public String getRenderedContent() {
return renderedContent;
}
public void setRenderedContent(String renderedContent) {
this.renderedContent = renderedContent;
}
public String getRenderedSummary() {
return renderedSummary;
}
public void setRenderedSummary(String renderedSummary) {
this.renderedSummary = renderedSummary;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getPublishAt() {
return publishAt;
}
public void setPublishAt(Date publishAt) {
this.publishAt = publishAt;
publicSlug = publishAt == null ? null : generatePublicSlug();
}
public boolean isDraft() {
return draft;
}
public void setDraft(boolean draft) {
this.draft = draft;
}
public void setBroadcast(boolean isBroadcast) {
broadcast = isBroadcast;
}
public boolean isBroadcast() {
return broadcast;
}
#JsonIgnore
public boolean isScheduled() {
return publishAt == null;
}
#JsonIgnore
public boolean isLiveOn(Date date) {
return !(isDraft() || publishAt.after(date));
}
public String getPublicSlug() {
return publicSlug;
}
public void addPublicSlugAlias(String alias) {
if (alias != null) {
this.publicSlugAliases.add(alias);
}
}
#JsonIgnore
public String getAdminSlug() {
return String.format("%s-%s", getId(), getSlug());
}
private String generatePublicSlug() {
return String.format("%s/%s", SLUG_DATE_FORMAT.format(getPublishAt()), getSlug());
}
#JsonIgnore
private String getSlug() {
if (title == null) {
return "";
}
String cleanedTitle = title.toLowerCase().replace("\n", " ").replaceAll("[^a-z\\d\\s]", " ");
return StringUtils.arrayToDelimitedString(StringUtils.tokenizeToStringArray(cleanedTitle, " "), "-");
}
#Override
public String toString() {
return "Post{" + "id=" + id + ", title='" + title + '\'' + '}';
}
}
Class Post even has 3 constructors named Post(){...}
Source: https://github.com/spring-io/sagan/blob/master/sagan-common/src/main/java/sagan/blog/Post.java
So, recall that the purpose of the constructor is to initialize (give them values).
So think of this model:
public class Car{
private String model; //Objects are null
private int year; // year = 0
Car(String model, int year ){
this.model = model;
this.year = year;
}
}
The Car object you create needs values for the model and the year. It would be great if you could just create a dummy car with just default values for each field, or take a string that looks like this:
"Ford 2016 or "Ford" and "2016" and create a Car object.
So, just create two more constructors with different signatures that accomplish that task.
Also, imagine we have another String field called owner. The owner of a car may not be know at the creation of this object, but your program may be able to function without it. So, we can use the same constructor above and the Car object's owner field will be set to null.
That's the purpose for multiple constructors. To give the programmer flexibility on saying what an object can be created from and which variables need to be initialized in the first place.
You may also find this useful:
Related
I have this condition (property rent system, rent is counted per night)
Owner has one or more property. Property has description, price, and isOccupied attribute.
The property can be: hotel (with 3 room types), flat/apartment, and house for homestay.
Through a registry function, a customer can order one or more property available at certain date.
Here are the pre-defined conditions for registry function:
There are 2 registered owners and customers in the system.
Owner 1 has 10 hotel rooms (standard type) for US$30 per night and 3 hotel rooms (suite type) for US$60 per night.
Owner 2 has 3 apartments for US$70 per night and 5 homestay house for US$20 per night.
Customers can rent one or more owner's property for a certain date.
To model the property, I use inheritance concept. For now, it looks something like this.
Property.java
public class Property {
private String description;
private int propertyPrice;
private String ownerName; // should it be here? or should it be made in another class?
private boolean isOccupied;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPropertyPrice() {
return propertyPrice;
}
public void setPropertyPrice(int propertyPrice) {
this.propertyPrice = propertyPrice;
}
}
Hotel.java
public class Hotel extends Property {
private String[] roomType;
private int[] roomCount;
public Hotel(){
this.roomType = new String[]{"Standard", "Deluxe", "Suite"};
this.roomCount = new int[]{0, 0, 0};
}
public String[] getRoomType() {
return roomType;
}
public void setRoomType(String[] roomType) {
this.roomType = roomType;
}
public int[] getRoomCount() {
return roomCount;
}
public void setRoomCount(int[] roomCount) {
this.roomCount = roomCount;
}
}
Apartment.java
public class Apartment extends Property {
private int roomCount;
public int getRoomCount() {
return roomCount;
}
public void setRoomCount(int roomCount) {
this.roomCount = roomCount;
}
}
Homestay.java
public class HomestayRoom extends Property {
private String parentName;
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
}
What makes me confused is, how can I define the pre-defined conditions for registry to model owner-property relation? Should I make the owner at another class? If so, how can I relate the properties and its owner?
Most of what you have done is correct, but you could also have a property type enum
public enum PropertyType{
HOTEL,APARTMENT,HOMESTAY
}
Now you're super class would be
public class Property {
private String description;
private int propertyPrice;
private String ownerName;
private boolean isOccupied;
private PropertyType pt;
....
}
A constructor for hotel would be
public Hotel(){
this.roomType = new String[]{"Standard", "Deluxe", "Suite"};
this.roomCount = new int[]{0, 0, 0};
super(PropertyType.HOTEL);
}
Similarly you could have constructors for Homestay and Apartment, with the extra line of super(PropertyType.HOMESTAY) and super(PropertyType.APARTMENT) respectively.
[Closed]
When calling the findAll() function from the JpaRepository I correctly get a list of the wanted Objects.
When inspecting the list, one can see that all the fields in an Object are set to null.
Checking the Database alle fields are set. Using findAll() on other Entities works perfectly fine.
#Entity
#Table(name = "loc_module")
public class LocModule implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Size(max = 255)
#Column(name = "name", length = 255, nullable = false)
private String name;
#NotNull
#Size(max = 255)
#Column(name = "filename", length = 255, nullable = false)
private String filename;
#Size(max = 2048)
#Column(name = "path", length = 2048)
private String path;
#ManyToOne
private LocOutputType outputType;
#ManyToMany(mappedBy = "modules")
#JsonIgnore
private Set<LocKey> keys = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public LocModule name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
public String getFilename() {
return filename;
}
public LocModule filename(String filename) {
this.filename = filename;
return this;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getPath() {
return path;
}
public LocModule path(String path) {
this.path = path;
return this;
}
public void setPath(String path) {
this.path = path;
}
public LocOutputType getOutputType() {
return outputType;
}
public LocModule outputType(LocOutputType locOutputType) {
this.outputType = locOutputType;
return this;
}
Any idea what could be causing this?
Thanks in advance!
The problem was finally solved and sadly it was completely out of my control.
Since I was Testing this on a Testing Environment somehow, someone copied the data one the table LocTable in form another table, without my knowledge.
The foreign key set for LocOutputType was therefor referring to a non existing LocOutputType.
Liquibase was then not able to map the rest of the Object.
Weirdly I did not get any sort of error message.
This is very stupid and I should somehow have seen it.
I will mark the question as closed.
I using RestController update data to db but I have problem. When i update value, if value from my update is null , it allways update data to db is null. I dont't want it. I want if 1 field with value is null from my request, i don't want update it.
This bellow my code :
Controller:
RestController
#RequestMapping("/api/products")
#Api(value = "ProductControllerApi",produces = MediaType.APPLICATION_JSON_VALUE)
public class ProductController {
#Autowired
private ProductService productService;
#PatchMapping("/{id}")
public ResponseEntity<ProductResDto> updateProduct(#RequestBody ProductReqDto productReqDto, #PathVariable String id) {
return ResponseEntity.ok(productService.updateProduct(product,id));
}
ProductReqDto:
public class ProductReqDto {
private String name;
private String type;
private String category;
private String description;
private Double prince;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrince() {
return prince;
}
public void setPrince(Double prince) {
this.prince = prince;
}
}
ProductResDto:
public class ProductResDto {
private String name;
private String type;
private String category;
private Double prince;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrince() {
return prince;
}
public void setPrince(Double prince) {
this.prince = prince;
}
}
MappingDto:
private ProductDto convertToProductDto(ProductReq product) {
return modelMapper.map(product, ProductResDto.class);
}
How to i handle method convertToProductDto only mapping with value not null. Because if , mapping one field : example : product_name = null , it insert to db null. I want if field ProductReq have value, it mapping and keep other different field in database(not set it null if not contain value from ProductReq) .
Example:
**ReqProductDto.class**
private String name;
private String type;
private String category;
private String description;
private Double prince;
but if user only update two field:
private String name;
private String type;
I want spring update field name, and field type user input and keep category,description,prince in my database. In my case, if user update two field: name, and field type,spring update it but spring set category,description,prince is null in my database. I don't want it.
Please help me, thanks.
You've tagged this as spring-boot, so I'm assuming you might be using controllers and validating their parameters. If that is the case, just do
import javax.validation.constraints.NotNull;
public class ProductReqDto {
#NotNull
private String name;
#NotNull
private String type;
#NotNull
private String category;
#NotNull
private String description;
#NotNull
private Double prince;
...
}
and use #Valid for your controllers like this
#PatchMapping("/{id}")
public ResponseEntity<ProductResDto> updateProduct(#RequestBody #Valid ProductReqDto productReqDto, #PathVariable String id) {
return ResponseEntity.ok(productService.updateProduct(product,id));
}
Then your object will be validated on instantiation.
What you want is mainly used for PATCH mapping.
IN a PUT mapping, all fields of an object need to override, but in a PATCH mapping only the fields which are provided needs to be overridden, others need not be changed.
So,
for an existing record,
employee{ employeeId = "A2RTD", empName = "satish", "country": "India"}
And, now one non-mandatory field mobileNo needs to be updated along with the country
DTO request will contain all field other than id, but only country & mobile no will not be null
In this scenario, we can use BeanUtils which is part of spring package
import org.springframework.beans.BeanUtils;
public static Object getDtoMapping(Object source, Object destination) {
BeanUtils.copyProperties(source, destination, getNullFieldNames(source));
return destination;
}
public static String[] getNullFieldNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> fieldNames = new HashSet<>();
for (PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null)
fieldNames.add(pd.getName());
}
String[] result = new String[fieldNames.size()];
return fieldNames.toArray(result);
}
Ths function "getNullFieldNames" will return fieldNames which have value null. So, those fields will not be mapped, as per 3rd optional paramter in BeanUtils
And, you need to pass
// PATCH
EmployeeDao emp = findById(empCode);
emp = (EmployeeDao) getDtoMapping(empUpdateDto, emp);
Here, in BeanUtil copyProperties, 3rd param is optional. If you give it works for PATCH mapping, if you don't give it behaves as PUT mapping.
Since, for PUT mapping, ignoring null as same as not ignoring.
You can use the same in POST, PUT mapping also.
// POST MAPPING
EmployeeDao emp = (EmployeeDao) getDtoMapping(empCreateDto, new Employee());
public class MyObject
{
public static enum Type {A, B, C, D;}
public static final int ID_MAIN = 1;
public static final int ID_MAIN_UK = 2;
public static final int ID_MAIN_US = 3;
public static final int ID_SUB = 4;
// lots more constants here
public static final String DESCRIPTION_1 = "Desc Full Name";
public static final String DESCRIPTION_2 = "Desc2 Full Name";
// lots more constants here
private int id;
public MyObject(final int id)
{
this.id = id;
}
//simple getter
public int getID() { return this.id;}
// real responsibility of the class is in the following two methods
public static String getDescription()
{
switch(id)
{
case MyObject.ID_MAIN:
case MyObject.ID_MAIN_UK:
return MyObject.DESCRIPTION_1;
case MyObject.ID_SUB:
return MyObject_Description_2;
default:
// throw IllegalArgException
}
}
public static Type getType(int id)
{
switch(id)
{
case MyObject.ID_MAIN:
case MyObject.ID_SUB:
return Type.A;
case MyObject.ID_MAIN_UK:
case MyObject.ID_MAIN_US:
return Type.B;
default:
return Type.Undefined;
}
}
}
Basically, there is an ID that maps to both a description and a type. This ID is passed in during construction of the class and it should map to a set of constants already contained in the class. If the id is not part of the list of constants, an error is thrown when trying to get the description that maps to the id and an 'Unknown' type is return if the type is queried. The ID maps a description to a set of constants. The same ID maps to a certain Type (defined as an enum).
This code is pretty ugly because there are tons of constants defined at the top, which makes the switch statements pretty bloated. Is there a simple way to refactor this without changing the public interface? It seems trivially simple, but it seems pretty ugly no matter how you slice it. How can I simplify these mappings to make the code more concise?
I was thinking about representing the mappings in a text file and having a manager class that held simple containers in a hashmap. When the manager class is constructed, it would create the objects by reading the text file and map them to an ID. When the manager is queried with the ID, it would just call the corresponding get method, for instance:
class Manager
{
private HashMap<int, MyObject> objectMap;
public Manager() {} //construct the object map
public String getDescription(int id) { return objectMap.get(id).getDescription();}
public Type getType(int id) { return objectMap.get(id).getType();}
}
class DataContainer
{
private String description;
private Type type;
public DataContainer(String desc, Type type) {//set mem vars}
public String getDescription() //simple getter
public Type getType() //simple getter
}
But this solution seems too complicated. Is there a better solution, preferably one that would keep everything in one class?
You can do something like following. This would be much cleaner and manageable.
public enum Type
{
MAIN(1, "Main Description"),
MAIN_UK(2, "Main UK Description"),
//....
//Define all the types
//....
UNKNOWN(-1, "Unknown Type");
private int id;
private String description;
private Type(int id, String description)
{
this.id = id;
this.description = description;
}
public static Type getById(int id)
{
for (Type type : Type.values())
{
if (id == type.getId())
{
return type;
}
}
return Type.UNKNOWN;
}
public final int getId()
{
return id;
}
public final String getDescription()
{
return description;
}
}
public class MyObject
{
private int id;
private Type type;
public MyObject(int id)
{
this.id = id;
this.type = Type.getById(id);
}
public int getId()
{
return id;
}
public Type getType()
{
return type;
}
public String getDescription()
{
return type.getDescription();
}
}
In Java enums can have methods. For example following one accepts ID and description and provides some accessors.
public enum Type {
MAIN(1, "desc1"),
UK(2, "desc2"),
SUB(4, "desc4");
private int id;
private String desc;
Type(int id, String desc) {
this.id = id;
this.desc = desc;
}
public String getDescription() {
return desc;
}
public int getType() {
//return id;
return 1+2 + 3+ id;
}
}
You could use that to improve design.
Suppose I have 2 beans:
Award
Employee
I add both of them in a collection. Based on this collection I want to generate a report using DynamicJasper using JRBeanCollectionDataSource.
I'm able to generate the report for a single bean, but for collection of different bean I cant create a report - I get an error.
Is it possible to create a report for two different beans at a time?
Are there any alternative solution to solve this task?
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.
An alternative for this can be use an SubReport and pass the List<Award> to the MainReport and the List<Employee> to the SubReport, doing that, you can set your SubReport as an extension of your MainReport, example:
MainReport:
|FieldAward1|FieldAward2|FieldAward3|...|YOUR SUBREPORT HERE|
SubReport:
|FieldEmployee1|FieldEmployee3|FieldEmployee3|...
Edit:
Even if it seems basic, I have to tell you that you should sort your list in a way to make each Object inside one list matches with its repective Object inside the another one.