Creating a free form BIRT report using Scripted Datasource - java

I am trying to create a free form BIRT report. The report is not consisted to rows which have the same columnNames in each row.
Instead, it is a free form report, which will be of the following form.
"Name: {FirstName} {LastName} Addess : {Address}
Phone# {Phone#}
....
....
"
I am using a scripted datasource, which essentially returns the Map containing the name value pairs of {FirstName, LastName, Address, Phone, and other fields}..
But I am not sure how to set the variables and how do I get the FirstName, LastName etc.
Should I try to use dynamic text.
I don't know of any way in which BIRT can handle non row related data.
Here's my open script of the dataset.
open:
util = new Packages.test.ReportsUtil();
reportsVO = util.getReportVO("ABC");
in fetch:
if(currentrow < totalrows) {
dataSetRow["FirstName"] = reportsVO.getPropValue("identity.FirstName");
dataSetRow["LastName"] = reportsVO.getPropValue("identity.LastName");
currentrow++;
} else {
return (false);
}
But I am not sure of how do I get access to the FirstName and LastName in the main layout page.
Thank you

The goal of a scripted data source is to allow you to leverage the logic inherent in your data model and benefit from any business rules that manipulate that data. In the end it still wants the data to be formed into a rather traditional row-based set.
You mention dynamic text and I think this would be a great use for the Java-based event handlers. You can use the logic in the Java object you had bound to the scripted data source to instead tie to an event in the life cycle of the report and get your non-relational data that way.
You can even call your Java object directly from a JavaScript event handler (much easier to plug into via the IDE) using the JS "Packages" construct.
There are many examples to help you get this done at the BIRT Exchange.

I did something similar (BIRT 3.7) but I used row["colName"] instead of dataSetRow["colName"] and that seems to work. I have my data in a list, and then each list item is a grid. I set the data binding in the list to the data set. The grid is able to see the value as row["colName"].

Related

Play Framework - How to build a web page with multiple MySQL queries

I've created my first Play Framework Website with Java using the official documentation. It has a single page where I display a list of items that can be filtered or modified.
I have a Controller class with a method:
public CompletionStage<Result> feedpostslist(String domain, String date, String state, int page, int resnum, String search) {
return feedRepository.getArticleList(domain, date, state, page, resnum, search).thenApplyAsync(articles -> {
FeedArticle[] list = new FeedArticle[articles.size()];
articles.toArray(list);
return ok(views.html.feedpostslist.render(list));
}, ec.current());
}
This method does a query to the DB (through feedRepository) and then display the result using the view feedpostslist.
Everything is fine but now I need to get other data from the DB to be used in the same web page (so multiple queries). How do I do this in Play Framework? I don't understand what is the best way to do that.
Should I do multiple DB request inside the method showed before (through feedRepository) and then pass all these informations to my view? I don't want to do a mess or even something too heavy to handle.
If the second query doesn't depend on the first one you can run them in parallel using combineAsync. This is a good example on how to do that:
https://github.com/playframework/play-samples/blob/2.8.x/play-java-ebean-example/app/controllers/HomeController.java#L85
If the second query depends on results on the first then there's nothing you can do but to wait for the first one to complete and run the second one.

JasperReports export to Excel uses only last set background color

Im pretty pretty new to Dynamic-Jasper, but due to work i had to add a new feature to our already implemented solution.
My Problem
The Goal is to add a Column to a report that consists only out of a background-color based on some Information. I managed to do that, but while testing I stumbled upon a Problem. While all my Columns in the html and pdf view had the right color, the Excel one only colored the fields in the last Color.
While debugging i noticed, that the same colored Fields had the same templateId, but while all Views run through mostly the same Code the Excel one showed different behavior and had the same ID in all fields.
My Code where I manipulate the template
for(JRPrintElement elemt : jasperPrint.getPages().get(0).getElements()) {
if(elemt instanceof JRTemplatePrintText) {
JRTemplatePrintText text = (JRTemplatePrintText) elemt;
(...)
if (text.getFullText().startsWith("COLOR_IDENTIFIER")) {
String marker = text.getFullText().substring(text.getFullText().indexOf('#') + 1);
text.setText("ID = " + ((JRTemplatePrintText) elemt).getTemplate().getId());
int rgb = TypeConverter.string2int(Integer.parseInt(marker, 16) + "", 0);
((JRTemplatePrintText) elemt).getTemplate().setBackcolor(new Color(rgb));
}
}
}
The html view
The Excel view
Temporary Conclusion
The same styles uses the same Objects in the background and the JR-Excel export messes something up by assigning the same Object to all the Fields that I manipulated there. If anyone knows of a misstake by me or potential Solutions to change something different to result the same thing please let me know.
Something different I tried earlier, was trying to set the field in an evaluate Method that was called by Jasper. In that method we assign the textvalue of each field. It contained a map with JRFillFields, but unfortunatelly the Map-Implementation denied access to them and just retuned the Value of those. The map was provided by dj and couldn't be switched with a different one.
Edit
We are using JasperReports 6.7.1
I found a Solution, where I replaced each template with a new one that was supposed to look exactly alike. That way every Field has its own ID guaranteed and its not up to chance, how JasperReports handles its Data internaly.
JRTemplateElement custom =
new JRTemplateText(((JRTemplatePrintText) elemt).getTemplate().getOrigin(),
((JRTemplatePrintText) elemt).getTemplate().getDefaultStyleProvider());
custom.setBackcolor(new Color(rgb));
custom.setStyle(((JRTemplatePrintText) elemt).getTemplate().getStyle());
((JRTemplatePrintText) elemt).setTemplate(custom);

Javascript changes dissapear when going back from servlet to JSP

Good evening,
I have a form on a JSP page that's connected to a servlet, that form has some dynamic parts using JavaScript like adding a row to a table or adding a text field based on the selected option on a select element, Actually my problem is that I have some validations on the servlet-side, so when I go to servlet to check the (National ID) for example if there's any problem or any violations to my validation I force to get back to the form using :
if (dbm.MatchIdNumber(Candidate.getRegNumber(), Candidate.getNationalID()) == false) {
out.println("<script>\n"
+ " alert('Your National Id does not match your Registration Number');\n"
+ "</script>");
out.println("<script>\n"
+ " window.history.go(-1);\n"
+ "</script>");
}
What happens is when I get back to the form I lose all the JavaScript changes, Which's very important.
I've been reading for a while that using ajax might be the optimal solution for me, but here is my questions:
Is there a way to call a java method from JavaScript or JQuery before getting to servlet without using ajax !?!
Is there a way to get back from the servlet to the jsp page with the ability to keep all the JavaScript Chages !?
If not !!, How to use ajax in my case ?!
Thank you so much
No. JavaScript runs on the user's browser and your Java code runs on your webserver, so basically the only way to communicate between the two is via HTTP requests.
If you don't want to use AJAX, you could provide all of the relevant info when you submit the form to the server for validation. You could pass all the info you need to re-generate the form as it was, like which new fields are there and such
First, you'll need to add a new webservice to your Java webapp which performs validation. To achieve this, you could either add additional logic to your servlet (so that it looks for a request parameter like "doValidation=1" and performs validation if it's there) or write a different servlet that handles validation itself. You'll need to decide the format it should expect the form data in and how it should return the validation information.
On your frontend page, you'll need to modify the behavior of the form so that, when you need to do validation, it performs a request to this webservice and passes along the form data. I would probably do this with jQuery and do something like jQuery.ajax(...) and pass the contents of the form as a JSON object.
When your validation servlet returns data from the ajax call, you'll need to update the form based on the data it provides. If I was doing it, I would probably just have the servlet return a JSON object like {errorMessage:"..."} and I would use jQuery to add an element to the form containing the text of the validation error when it occurs. If the servlet returns an empty string or JSON object or something, I would consider it a validation success.

how to forward back to JSP page without losing the data entered in fields?

I have a simple MVC-based JSP application. Something like:
*.jsp -> ControllerServlet -> *Command.java -> *Service.java -> *DAO.java -> Oracle db
A typical link in the application looks like this:
myapp/controller?cmd=ShowEditUser&userid=55
Which causes ShowEditUserCommand.java execute() method to run and will forward to editUser.jsp
In editUser.jsp, they fill in the fields, then click Save which posts to myapp/controller?cmd=ModifyUser which runs ModifyUserCommand.java execute() method which modifies the user data and forwards to viewUser.jsp.
Everything works fine.
The problem is, in ModifyUserCommand.execute() I'm checking to see if the username is unique. If they try to enter a username that already exists, I set an error value to true and errorMessage value to Already in use.
Then because of the error I forward to the original editUser.jsp (not viewUser.jsp) and the error is displayed above the form.
MY PROBLEM IS (finally! ;) -- when the user is returned to editUser.jsp with the error message displayed, the data they entered in the fields is all blanked out. How can I set it so whatever they entered in the fields is still in place?
Any suggestions or advice are greatly appreciated!
Rob
Simplest way would be to pass the form fields back to your editUser.jsp in your forward action in ModifyUserCommand.execute(). You can do that with individual parameters i.e.
editUser.jsp?field1=1&field2=2
Alternatively, you could pass data with other methods - i.e. encoded JSON.
You can then process your fields in your editUser.jsp via the page's request object and set your form field values accordingly.
There may be other ways to do this depending on what underlying framework (if any) you are using. But this is a basic way of approaching it.

How to implement a Lazy List using SmartGWT and SQL

I was trying all of yesterday to try and integrate a SQL Database with SmartGWT for a lazy list but I just couldn't figure out how to implement it. (JavaDoc, and example of a lazy list)
What I want to do is create a list of a bunch of "sites" all over the world. The problem is there will probably be about a million of them, so I'm trying to load as few as possible at a time. Each site in my DB has an address, so I'm trying to sort them in the tree structure like (Country->State->City->Sites). Every time you go down a level there will be a query to the DB asking for all of the next level (Whether that be all the cities that have sites in the state chosen, or what ever).
Any help is greatly appreciated.
ALSO:
In the example linked the folders and leafs are the type of element, is there a way to keep folders, folders, and then leafs a separate type of object?
After a while I finally got it. I ended up creating my own RPC that would serve up an array of strings that would represent the names of all the TreeNodes for the next level.
So entry point would be:
private NodeServiceAsync nodesRpc; //The RPC that grabs more nodes
private Tree data; //The data structure to hold all of the nodes
private ColumnTree list; //The GUI element that is shown on in the browser
public void onModuleLoad() {
nodesRpc = (NodeServiceAsync) GWT.create(NodeService.class);
data = new Tree();
list = new ColumnTree;
list.setAutoFetchData(true);
list.setLoadDataOnDemand(true);
list.addNodeSelectedHandler(new NodeSelectedHandler () {
public void onNodeSelected(NodeSelectedEvent event) {
if(/*Node is folder and hasn't been opened before*/) {
//Get More Nodes
AsyncCallback<String[]> callback = new NodeGetter<String[]>();
nodesRpc.getData(event.getNode(), callback);
}
else if(/*Node is not a folder (at the end) */) {
//Do something else
}
}
});
list.setData(data); //Make the GUI Element Represent The Data Structure
RootPanel.get().add(list); //Add to screen
}
The serverlet on the server side creates the query, executes, then translates the ResultSet into an array of Strings and passes that back. All the callback has to do, back on the client side, is translate that array into an array of TreeNodes and attach them to the original Node that was clicked on. Finally after all of this the GUI element is redrawn with the new nodes.
I was surprised that there was very little down time between node loads (less then 1 sec) even when sometimes a hundred or so nodes where being queried then displayed.
Note there is also a Pro version of the product which includes SQL connectivity like this out of the box (for Java server platforms). Showcase here:
http://www.smartclient.com/smartgwtee/showcase/
The SQL connector in the Pro product includes load on demand / data paging, search, and all 4 CRUD operations, as well as DataSource Wizards that can generate a working SQL DataSource for an existing database table if you just enter JDBC settings.
Note the Pro product doesn't require SQL, that's just one of the things it can connect to.

Categories