How To Pass a JRBeanCollectionDataSource to iReport? - java

I'm currently trying to use jasper to help me create reports. I have the information and data that I want displayed in this method:
private void writeToFile(final List<ScenarioLoadModel> sceneLoadModel) throws Exception {
final BufferedWriter bw = new BufferedWriter(new FileWriter("/Uma/nft/result.psv"));
for (final ScenarioLoadModel slm : sceneLoadModel) {
bw.write(slm.getScenarioId() + PSP + slm.getScenarioId() + PSP + slm.getScenarioConfig().getName() + PSP + slm.getLoad() + PSP + "" + EOL);
if (!slm.getScenarios().isEmpty()) {
final int tempCount = slm.getScenarios().get(0).getTemplates().size();
final int sceneCount = slm.getScenarios().size();
for (int tempIdx = 0; tempIdx < tempCount; tempIdx++) {
String id = null;
int pass = 0;
int fail = 0;
final Map<String, BigDecimal> metricMap = new HashMap<String, BigDecimal>();
final DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset();
for (int sceneIdx = 0; sceneIdx < sceneCount; sceneIdx++) {
final Template temp = slm.getScenarios().get(sceneIdx).getTemplates().get(tempIdx);
if (temp.isError()) {
fail++;
} else {
pass++;
}
if (sceneIdx == 0) {
id = temp.getId();
}
final MetricGroupModel mgm = slm.getScenarios().get(sceneIdx).getMetricGroupModel().get(tempIdx);
if (mgm != null) {
for (final MetricModel mm : mgm.getMetricModel()) {
for (final MetricValue mv : mm.getMetricValue()) {
dataset.add(mv.getValue(), new BigDecimal(0.0), mv.getType(), id);
}
}
}
}
final TemplateConfig tc = TemplateManager.getTemplateConfig(id);
bw.write(slm.getScenarioId() + PSP);
bw.write(id + PSP + tc.getName() + PSP + 1 + PSP + pass + "/" + fail);
for (final Object row : dataset.getRowKeys()) {
final Number mean = dataset.getValue((String) row, id);
bw.write(PSP + row + PSP + mean);
}
bw.write(EOL);
}
}
}
bw.close();
}
From my understanding I create Beans and then put them all in a Bean Factory, to create my object that will be ready to be passed to iReport.
How can I put all this information into a Bean? I essentially want the bean to include the scenario/test case and whether or not it passed. (This is for test automation)

I tried to read your code to make a a best guess at what columns you would want, but with no context, I have no clue. All the bean is a pojo, with private fields and public getters and setters.
Assuming there is no grouping and essentially each ScenarioLoadModel will correspond to one row in the report you would end up with a bean like this:
public class ScenariaResults {
private String id;
private String name;
private String load;
private int passCount;
private int failCount;
public ScenariaResults(String id, String name, String load, int passCount,
int failCount) {
super();
this.id = id;
this.name = name;
this.load = load;
this.passCount = passCount;
this.failCount = failCount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoad() {
return load;
}
public void setLoad(String load) {
this.load = load;
}
public int getPassCount() {
return passCount;
}
public void setPassCount(int passCount) {
this.passCount = passCount;
}
public int getFailCount() {
return failCount;
}
public void setFailCount(int failCount) {
this.failCount = failCount;
}
#Override
public String toString() {
return "ScenariaResults [id=" + id + ", name=" + name + ", load="
+ load + ", passCount=" + passCount + ", failCount="
+ failCount + "]";
}
}
So basically in the code you have above you build instances of ScenarioResults and add them to a list. Once you have the list, all you need to do is create a JRDataSource:
List<ScenarioResults> dataBeanList = ...call your method to get the list of results
//create the datasource
JRDataSource dataSource = new JRBeanCollectionDataSource(dataBeanList);
Now when designing the report in iReport it can be a little tricky to get the fields imported automatically. Basically first add your project with the bean to the classpath in iReports (could just point it to the bin folder or jar file`): Tools -> options -> classpath tab. Now follow these steps to add the fields.
Click the following icon:
Select the JavaBean Datasource tab.
Enter the classname of your bean. (ex. ScenarioResults)
Click Read attributes
Highlight the fields you want in the report and click Add Selected Field(s).
Click OK.
Now if you want to test what the report looks like with data, and not just an empty datasource, this is where the Factory comes in. It is only for testing while using iReport. You need to create a class that will essentially create a dummy data set for you. It should look something like:
import java.util.ArrayList;
import java.util.List;
public class ScenarioResultsFactory {
public static List<ScenarioResults> createBeanCollection() {
List<ScenarioResults> list = new ArrayList<ScenarioResults>();
list.add(new ScenarioResults("1", "test", "load", 10, 5));
//add as many as you want
return list;
}
}
Now you need to create a Datasource pointing to it in iReport.
Next to the Datasource dropdown in the toolbar click the icon with the tooltip `Report Datasources.
Click New.
Select JavaBeans set datasource. Click Next.
For name enter ScenarioResultsFactory.
For the Factory class you need to put the classname including package. So if the class is in the com package you should have com.ScenarioResultsFactory here.
For the static method put createBeanCollection if not already there.
Check the Use field description check box. Click Test to make sure it worked.
Click Save.

Related

Is there a way to make Dozer map fields without getter or setters? (Or, what mapper can do this?)

Here's an article on Dozer: https://www.baeldung.com/dozer. It's a mapper that uses reflection to map same-name fields from one object to another (of a completely unrelated class).
I was wondering if this works flexibly with private fields, getters, and setters. That is,
Will private String a map to another object's private String a without either having any getters or setters?
What if only one side has a getter or setter (and the private field is named something different to make sure it's not directly accessing private fields)?
What if one has a getter and the other has a setter for totally mismatching private fields? (But the getter and setter names match.)
I wrote a test program to run in https://www.jdoodle.com/online-java-compiler:
import org.dozer.DozerBeanMapper;
public class Main {
public static class MySource {
// a -> a
private String a;
// getB() -> b
private String hidden_b;
public String getB() { return hidden_b; }
// c -> setC(c)
private String c;
// getD() -> setD(d)
private String hidden_d;
// proper getters and setters on both sides
private String proper;
public String getProper() { return proper; }
// public void setProper(String proper_) { proper = proper_; }
public MySource() {
a = "A Room with a View";
hidden_b = "The Bridge of San Luis Rey";
c = "Civilwarland in Bad Decline";
hidden_d = "Darkness at Noon";
proper = "This should copy, at minimum.";
}
public void print() {
System.out.println("Source");
System.out.println("================================");
System.out.println("a = " + a);
System.out.println("hidden_b = " + hidden_b);
System.out.println("c = " + c);
System.out.println("hidden_d = " + hidden_d);
System.out.println("--------------------------------");
System.out.println("proper = " + proper);
System.out.println("");
}
}
public static class MyTarget {
private String a;
private String b;
private String hidden_c;
private String hidden_e;
public void setC(String param) { hidden_c = param; }
public void setD(String param) { hidden_e = param; }
private String proper;
// public String getProper() { return proper; }
public void setProper(String proper_) { proper = proper_; }
public MyTarget() {}
public void print() {
System.out.println("Target");
System.out.println("================================");
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("hidden_c = " + hidden_c);
System.out.println("hidden_e = " + hidden_e);
System.out.println("--------------------------------");
System.out.println("proper = " + proper);
System.out.println("");
}
}
public static void main(String args[]) {
MySource s = new MySource();
s.print();
System.out.println("Now dozing...");
System.out.println("");
MyTarget t = new DozerBeanMapper().map(s, MyTarget.class);
t.print();
}
}
Note that to run the above code you must add a maven dependency:
Group ID: net.sf.dozer
Artifact ID: dozer
Version: 5.5.1
And also you must try executing a few times because of random timeouts depending on whether the dependency loads fast enough.
Anyway, my output was:
Source
================================
a = A Room with a View
hidden_b = The Bridge of San Luis Rey
c = Civilwarland in Bad Decline
hidden_d = Darkness at Noon
--------------------------------
proper = This should copy, at minimum.
Now dozing...
Target
================================
a = null
b = null
hidden_c = null
hidden_e = null
--------------------------------
proper = This should copy, at minimum.
So, it appears Dozer only works through a getter on the source and a setter on the target, which is disappointing. Or, I'm not using it correctly!
Is there a way to make Dozer more flexible? Or, another mapper library that can achieve this?
Okay, here are my findings. Hopefully this helps someone.
Dozer 5.5.1 was supposed to be able to do this via "class-level is-accessible." However, there was a bug. It was fixed for future releases, e.g. Dozer 6.1+. (The package moved to a new group, org.github.dozermapper.) The steps were a little complicated though, and eventually I gave up to try ModelMapper, which was much nicer. So here's my code.
Include this package:
Group ID: org.modelmapper
Artifact ID: modelmapper
Version: 2.3.2
Here's how to use it:
import org.modelmapper.ModelMapper;
import org.modelmapper.config.Configuration;
public class Main {
public static class MySource {
// a -> a
private String a;
// getB() -> b
private String hidden_b;
public String getB() { return hidden_b; }
// c -> setC(c)
private String c;
// getD() -> setD(d)
private String hidden_d;
// proper getters and setters on both sides
private String proper;
public String getProper() { return proper; }
// public void setProper(String proper_) { proper = proper_; }
public MySource() {
a = "A Room with a View";
hidden_b = "The Bridge of San Luis Rey";
c = "Civilwarland in Bad Decline";
hidden_d = "Darkness at Noon";
proper = "This should copy, at minimum.";
}
public void print() {
System.out.println("Source");
System.out.println("================================");
System.out.println("a = " + a);
System.out.println("hidden_b = " + hidden_b);
System.out.println("c = " + c);
System.out.println("hidden_d = " + hidden_d);
System.out.println("--------------------------------");
System.out.println("proper = " + proper);
System.out.println("");
}
}
public static class MyTarget {
private String a;
private String b;
private String hidden_c;
private String hidden_e;
public void setC(String param) { hidden_c = param; }
public void setD(String param) { hidden_e = param; }
private String proper;
// public String getProper() { return proper; }
public void setProper(String proper_) { proper = proper_; }
public MyTarget() {}
public void print() {
System.out.println("Target");
System.out.println("================================");
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("hidden_c = " + hidden_c);
System.out.println("hidden_e = " + hidden_e);
System.out.println("--------------------------------");
System.out.println("proper = " + proper);
System.out.println("");
}
}
public static void main(String args[]) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
.setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);
MySource s = new MySource();
s.print();
System.out.println("Now dozing...");
System.out.println("");
MyTarget t = modelMapper.map(s, MyTarget.class);
t.print();
}
}
Here's my output:
Source
================================
a = A Room with a View
hidden_b = The Bridge of San Luis Rey
c = Civilwarland in Bad Decline
hidden_d = Darkness at Noon
--------------------------------
proper = This should copy, at minimum.
Now dozing...
Target
================================
a = A Room with a View
b = The Bridge of San Luis Rey
hidden_c = Civilwarland in Bad Decline
hidden_e = null
--------------------------------
proper = This should copy, at minimum.
The fourth case didn't copy over but I don't really care about that case. I think it can easily achieved with a different ModelMapper configuration though. Maybe try LOOSE copying. Or worst case, manually bind the getter and setter methods in the config.
Dozer by default uses getters and setters, however you can tell Dozer (via mapping) to access the fields directly
http://dozer.sourceforge.net/documentation/custommethods.html
BTW, Dozer 5 and 6 contains an API based mapping as well.

Java Variable from other class

I have 3 classes: Main, AutoHuur, Auto. Everythign works but 1 thing. I can't seem to get the "Prijs" variable from my Auto.class to display in my toString in my AutoHuur.class. It keeps showing up as 0. Why is this? (I know I initialize it to 0 if it's a null, but why is it a null and not the value from the Auto.class variable prijsPerDag?) Thank you
Main.class:
public class Main{
public static void main(String[] args) {
AutoHuur ah1 = new AutoHuur();
System.out.println("Eerste autohuur:\n" + ah1 + "\n");
Klant k = new Klant("Mijnheer de Vries");
k.setKorting(10.0);
ah1.setHuurder(k);
Auto a1 = new Auto("Peugeot 207", 50.0);
ah1.setGehuurdeAuto(a1);
ah1.setAantalDagen(4);
System.out.println("Eerste autohuur:\n" + ah1 + "\n");
AutoHuur ah2 = new AutoHuur();
Auto a2 = new Auto("Ferrari", 3500.0);
ah2.setGehuurdeAuto(a2);
ah2.setHuurder(k);
ah2.setAantalDagen(1);
System.out.println("Tweede autohuur:\n" + ah2 + "\n");
System.out.println("Gehuurd: " + ah1.getGehuurdeAuto());
System.out.println("Gehuurd: " + ah2.getGehuurdeAuto());
}
}
Autohuur.class:
public class AutoHuur {
private Klant huurder;
private Auto gehuurdeAuto;
private Auto prijs;
private Integer aantalDagen;
public AutoHuur(){
}
public void setHuurder(Klant nwH){
huurder = nwH;
}
public void setGehuurdeAuto(Auto nwGA){
gehuurdeAuto = nwGA;
}
public Auto getGehuurdeAuto(){
return gehuurdeAuto;
}
public Auto getPrijs(){
return prijs;
}
public void setAantalDagen(Integer nwD){
aantalDagen = nwD;
}
public String toString(){
String s = "";
if (gehuurdeAuto == null){
s = s + "er is geen auto bekend\n"; }
else {
s = s + gehuurdeAuto; }
if (huurder == null){
s = s + "er is geen huurder bekend\n"; }
else {
s = s + huurder; }
if (aantalDagen == null){
s = s + "aantal dagen: 0"; }
else {
s = s + "aantal dagen: " + aantalDagen; }
if (prijs == null){
s = s + " en dat kost 0.0"; }
else {
s = s + " en dat kost" + prijs; }
return s;
}
}
Auto.class:
public class Auto {
private String type;
private Double prijsPerDag;
public Auto(String tp, Double nwPr){
type = tp;
prijsPerDag = nwPr;
}
public void setPrijsPerDag(Double prPd){
prijsPerDag = prPd;
}
public Double getPrijsPerDag(){
return prijsPerDag;
}
public String toString(){
String s = type + " met prijs per dag: " + prijsPerDag + "\n";
return s;
}
}
In AutoHuur.class you can get your prijsPerDag variable from Auto.class using an Auto object, e.g.:
gehuurdeAuto.getPrijsPerDag()
You can calculate the price:
aantalDagen * gehuurdeAuto.getPrijsPerDag()
Is this what would you like to do?
You have to remove the first System.out becasuse in Main.java your instance AutoHuur is empty, so when your want to print the result , the out will be values empty.
The variable prijs is an object, which is initialized to null when an instance of AutoHuur is created. Since prijs is never set, it is always null.
That's why prijs == null always evaluates to true.
You need to set prijs somewhere.
It seems that you need to work on your design desicions. You are, for example, using an Auto class name, while it is in fact a link between a daily charge and a car type. If each link is represented by such an object (in your case Auto), then it absolutely makes no sense to have more than one instance.
For example,
new Auto("Peugeot", 40.0);
new Auto("Peugeot", 40.0);
is technically perfectly valid, but it is just not logical.
Furthermore, if a class holds data of some kind, then it's good to delegate operations upon that data also to that class.
class Auto {
private String type;
private double pricePerDay;
public double calculateTotalPrice(int numberOfDays) {
return numberOfDays * this.pricePerDay;
}
}

How to return a private variable

Ok so I'm trying to get a better understanding of how to return a private variable from a class that I have created. I've only provided a small snippet of my main program to explain my question, so if more information is needed please let me know. My goal is to return a string from the class (working great), but also be able to return the private variables individually as needed (example used below is "flight_number").
public class Flights {
private String dest_city, dest_state, departureDate, departureTime;
private int flight_number;
public Flights(String city, String state, String dDate, String dTime, int flightNumber) {
dest_city = city;
dest_state = state;
departureDate = dDate;
departureTime = dTime;
flight_number = flightNumber;
}
public String toString() {
return "Flight number: " + flight_number + " Destination: " + dest_city + "," + dest_state + " Departing on:" + departureDate + " at" + departureTime + ".";
}
}
public class dummy {
public static void main(String[] args) {
// Uses the constructor to set values
Flights flight1 = new Flights("Houston", "Texas", "12/20/2014", "12:40 pm", 100);
System.out.println(flight1);
System.out.println(flight_number); // Error: `flight_number` cannot be resolved to a variable.
}
}
You need to add a public getter in Flights and call it from main:
public class Flights {
// all the private fields
public int getFlightNumber() {
return this.flight_number;
}
}
In Main:
public static void main(String[] args) {
Flights flight1 = new Flights("Houston", "Texas"); //...
System.out.println(flight1);
System.out.println(flight1.getFlightNumber()); // call the getter
}
You should start with an editor like eclipse and that should help you get started quickly. Getters and Setters is what you need, but start with Eclipse and you should do better.

Update a single variable of a class in an ArrayList of class in java

I have a class Components:
public class Components {
int numberOfNets;
String nameOfComp;
String nameOfCompPart;
int numOfPin;
public components(int i, String compName, String partName, int pin) {
this.numberOfNets = i;
this.nameOfComp = compName;
this.nameOfCompPart = partName;
this.numOfPin = pin;
}
}
Inside another class I created an arraylist of Components class:
List<Components> compList = new ArrayList<Components>();
Later in the code, I am adding the elements in List in this way:
compList.add(new Components(0,compName,partName,0));
See, here numberOfNets and numOfPin variables in Components class are initiated with 0 values. But these values are getting calculated/incremented in a later part of code and hence I need to update the new values of only these two variables in each list element. Now from ArrayList doc I get the idea of updating a list element using its index by set operation. But I am confused how to set/update a particular variable of a class in an ArrayList of a class. I need to update only these two mentioned variables, not all of the four variables in Components class. Is there any way to do that?
You should add getter/setter to your component class so that outer class can update component's members
public class Components {
private int numberOfNets;
private String nameOfComp;
private String nameOfCompPart;
private int numOfPin;
public components(int i, String compName, String partName, int pin) {
setNumberOfNets(i);
setNameOfComp(compName);
setNameOfCompPart(partName);
setNumOfPin(pin);
}
public void setNumberOfNets(int numberOfNets) {
this.numberOfNets = numberOfNets;
}
// Similarly other getter and setters
}
You can now modify any data by using following code because get() will return reference to original object so modifying this object will update in ArrayList
compList.get(0).setNumberOfNets(newNumberOfNets);
Example code.
public class Main {
public static void main(String[] args) {
List<Components> compList = new ArrayList<Components>();
compList.add(new Components(0, "compName", "partName", 0));
System.out.println(compList.get(0).toString());
compList.get(0).numberOfNets = 3;
compList.get(0).numOfPin = 3;
System.out.println(compList.get(0).toString());
}
}
Your class.
public class Components {
int numberOfNets;
String nameOfComp;
String nameOfCompPart;
int numOfPin;
public Components(int i, String compName, String partName, int pin) {
this.numberOfNets = i;
this.nameOfComp = compName;
this.nameOfCompPart = partName;
this.numOfPin = pin;
}
public String toString() {
return this.numberOfNets + " " + nameOfComp + " " + nameOfCompPart
+ " " + numOfPin;
}
}
The output:
0 compName partName 0
3 compName partName 3

Getting Data in JList via JDBC - The missing link

I've been stuck at a seemingly simple problem for hours and I just can't find the solution. I'm trying to implement a very simple Forum in Java and I'm trying to load the entrys at the moment.
My forum is a JList that is filled with JPanels and that accepts entries via the JLists DefaultListModel and the addMessage method. So if I add an entry without the database it looks like this:
MessageList m = new MessageList();
m.addMessage("NAME AUTOR", "<html><body style='width: 675px;'>Lorem ipsum dolor sit amet.", "22.01.13", "SOA");
The messageList class looks like this:
public class MessageList extends JList{
DefaultListModel messageModel = new DefaultListModel();
MessageRenderer messageRenderer = new MessageRenderer();
public MessageList( ){
this.setCellRenderer(messageRenderer);
this.setModel(messageModel);
}
public void addMessage(String author, String text, String date, String tag){
messageModel.addElement(new Message(author, text, date, tag));
}
}
I've also written the Code for getting an ArrayList (called allBtr) with the Message Objects (called ConBeitrag) from the database:
ArrayList<ConBeitrag> allBtr = new ArrayList<ConBeitrag>();
ConBeitrag conBtr = new ConBeitrag();
try {
allBtr = conBtr.getAllBtr();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The message objects look like this:
public class ConBeitrag {
private int beitragid;
private int projektid;
private int mitarbeiterid;
private String beitragText;
private String erstellt_am;
private String geaendert_am;
private String schlagwort1;
private String schlagwort2;
private MdBeitrag mdBtr = new MdBeitrag();
public ConBeitrag (){
}
public ConBeitrag(int beitragid, int projektid, int mitarbeiterid, String beitragText, String erstellt_am, String geaendert_am){
this.beitragid = beitragid;
this.projektid = projektid;
this.mitarbeiterid = mitarbeiterid;
this.erstellt_am = erstellt_am;
this.geaendert_am = geaendert_am;
this.beitragText = beitragText;
this.schlagwort1 = schlagwort1;
this.schlagwort2 = schlagwort2;
}
public ArrayList<ConBeitrag> getAllBtr() throws SQLException{
MdBtrInterface modInt;
modInt = new MdBeitrag();
ArrayList<ConBeitrag> AlBtr = modInt.getAllBtr();
for(ConBeitrag object: AlBtr){
System.out.println(object.beitragText);
}
return AlBtr;
}
}
Now what would be the smartest way to get the ArrayList into a form that I can pass into the addMessage method? I've kind of approached this from the GUI end, then from the database end, and now I'm stuck in the middle.
Overwritten toString() method:
#Override
public String toString() {
return mitarbeiterid + beitragstext + erstellt_am + schlagwort1 + schlagwort2;
}
"The messages are stored inside the ArrayList as Objects if that helps. So if I run "System.out.println(allBtr);" it gives me "[ConBeitrag#48f4104f, ConBeitrag#f5ad7f4, ConBeitrag#1517dc0c]"
You need to override the toString method in your ConGeitrag class. Something like this.
public class ConBeitrag {
...
#Override
public String toString(){
return author + ", " + text + ", " + date + ", " + tag;
}
}
You can make the return any format you want. Test this one out and make changes as desired to the format.
Try this out as a Helper method (after you've overridden the toString)
public JList createJList(ResultSet rs){
DefaultListModel model = new DefaultListModel();
while (rs.next()){
String author = rs.getString("author"); // Just an example. You may
String text = rs.getString("text"); // need to retrieve your
String date = rs.getString("date"); // data differently
String tag = rs.getString("tag");
Message message = new Message(author, text, date, tag);
model.addElement(message);
}
JList list = new JList(model);
return list;
}
I don't really see a need for a Custom JList for this situation.
Test run: output : 3testtestnullnull. Besides the formatting, it works fine
public class ConBeitragTest {
public static void main(String[] args) {
ConBeitrag con = new ConBeitrag(1, 2, 3, "test", "test", "test");
System.out.println(con);
}
}
class ConBeitrag {
private int beitragid;
private int projektid;
private int mitarbeiterid;
private String beitragText;
private String erstellt_am;
private String geaendert_am;
private String schlagwort1;
private String schlagwort2;
public ConBeitrag() {
}
public ConBeitrag(int beitragid, int projektid, int mitarbeiterid, String beitragText, String erstellt_am, String geaendert_am) {
this.beitragid = beitragid;
this.projektid = projektid;
this.mitarbeiterid = mitarbeiterid;
this.erstellt_am = erstellt_am;
this.geaendert_am = geaendert_am;
this.beitragText = beitragText;
this.schlagwort1 = schlagwort1; // This is null
this.schlagwort2 = schlagwort2; // This is null
}
#Override
public String toString() {
return mitarbeiterid + beitragText + erstellt_am + schlagwort1 + schlagwort2;
}
}

Categories

Resources