Passing a variable and query to Jasper report - java

Is it possible to pass both an SQL query, e.g. (<![CDATA[$P!{SQL}]]>), and a variable $V as parameters to a Jasper report at the same time?
Also, how can I pass the variable $V to my Jasper report using Java?

Often it is desired to just transform some parameter in order to use it in a query (in this case, the following works :) ).
E.g. (pseudo code - Groovy syntax!)
parameter:
filtParamUserName = "foo"
"variable" (technically not: in this case another parameter following it)1:
sqlCondUserName = $P{filtParamUserName} ? " and user_name = '$P{filtParamUserName}'" : ""
thus you could easily use it in your query like:
select * from bar where 1=1 $P{sqlCondUserName}
1: you have to set the Default Value Expression of the sqlCondUserName and Is For Prompting = false

A variable is something that varies during the report generation, like the number of pages for example. So a variable ($V) is not something you can pass to a report. You may pass any value from your Java code to the report as a parameter ($P), though.

Related

What's the difference between `:path-param` and `{path-param}` in Java Spark?

I'm working on a REST server built with Java Spark, and I was wondering about the difference between the following two syntaxes for defining path parameters, using :path-parameter vs {path-parameter}:
path("/containers/:container-id", () -> { ...} )
path("/shipments/{shipment-id}", () -> { ... } )
At one point, when querying the path parameters on the path /{handler-id} (which is nested inside /v1 and /handlers), I had to change the syntax from the : form to the {} form to get Spark to not return null when querying the parameters for handler-id.
So what's the difference between these two syntaxes?
The only syntax for defining a parameter in a path is :path-param.
Querying the value of this parameter is done by String paramVal = request.params(":path-param") (the colon is optional when querying).
Or, if you want to get a map with all the parameters names-values you'll go request.params();
I'm not sure about why you got null when querying your param, but I'm guessing you used request.queryParams(":path-param");. But this API is used not to query a path-params like you wanted, but to query a query params which are parameters in the form of path like /api/users?userId=1234.
Summary
Path Definition URL in browser Query
--------------- ---------------------------- -----------------------------------
/api/users/:id <host>/api/users/1234 request.params("id") ==> 1234
/api/users <host>/api/users?id=1234 request.queryParams("id") ==> 1234
Note that the returned value is always a String and you'll have to cast if needed.

How to use variable in JDBC Object? Jmeter

I have a JMeter job that is performing some UI tests on a webpage, it should then store the text value of an object in a variable called "impid"
var vars = org.apache.jmeter.threads.JMeterContextService.getContext().getVariables()
var importID = WDS.browser.findElement(org.openqa.selenium.By.xpath('html/body/table[2]/tbody/tr[3]/td[6]/table[1]/tbody/tr[5]/td[2]/strong')).getText()
vars.put('impid','importID')
I believe that part is working, I then want the pass the value of that variable into a mysql JDBC Request, like so -
select id, fileName, timeEntered, timeStarted, timeCompleted, comments from netdespatch.fileImportStore where id = ${impid};
But the varialbe is just being used as the "name" it is not being converted into the variable value..
I'm sure someone know what i'm doing wrong..
I believe that part is working
how do you know? Given your XPath syntax I don't believe it matches anything.
Your select query looks good so I would recommend double checking your ${impid} variable using Debug Sampler and View Results Tree listener combination.
You can also try printing the variable value into jmeter.log file right from the WebDriver Sampler like:
WDS.log.info('importID value == ' + importID)
References:
XPath Tutorial
How to Debug your Apache JMeter Script
String s ="select id, fileName, timeEntered, timeStarted, timeCompleted, comments from netdespatch.fileImportStore where id = ?";
PreparedStatement preparedStatement = dbConnection.prepareStatement(s);
preparedStatement.setInt(1, impid);
Use place holder '?' and then bind with sentInt (or adequate method for other types)
I worked out the issue, the variable I was passing between Webdriver and JDBC needed to be a jmeter UDV..so
I have a UDV called impID
grabbed my value from webdriver and put it in the impID variable
var vars = org.apache.jmeter.threads.JMeterContextService.getContext().getVariables()
var importID = WDS.browser.findElement(org.openqa.selenium.By.xpath('html/body/table[2]/tbody/tr[3]/td[6]/table[1]/tbody/tr[5]/td[2]/strong')).getText()
vars.put('impID',importID)
this puts the value of importID into the UDV impID
Then on the JDBC request, use a "Prepared Select Statement"
select id, fileName, timeEntered, timeStarted, timeCompleted from nd.fileImportStore where id = ?
and in Parameter Value enter = ${impID}
And that worked :)

Invoking procedure defaults without binding values to parameters in Jdbc

I am trying to call a PL/SQL procedure which has defaults defined for some of its parameters. I am doing this using CallableStatement in JDBC.
This procedure has a large number of parameters with defaults defined. I do not want to explicitly set the defaults in the Java code. Doing this would make maintaining the code harder. If the PL/SQL code changes , would have to make the same changes in the Java code too.
Is it possible to accomplish this in JDBC ? For instance just bind values to the parameter you are interested in and ignore the rest.
I tried this on the following sample procedure :
-- PURPOSE: Takes a parameter which has defaults set. Returns the value of the same parameter
-- Example of: FUNCTION that takes a parameter with DEFAULT values
FUNCTION handle_defaults(empId IN NUMBER DEFAULT 20 , empCity IN VARCHAR2) RETURN NUMBER IS
BEGIN
RETURN empId;
EXCEPTION
WHEN others THEN
dbms_output.put_line('Error!');
END handle_defaults;
Here is the relevant portions of the code (NOTE: Have stripped off the try catch block , cleaning up of database resources etc for sake of readability)
// Create a database connection
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
// Create a query string
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
// Create a Callable Statements
callStmt = conn.prepareCall(queryStr);
// Bind values to the IN parameter
callStmt.setString(3, "Mumbai");
// Register OUT parameter
callStmt.registerOutParameter(1, java.sql.Types.NUMERIC);
// Execute the Callable Statement
callStmt.execute();
// Retrieve the value of the OUT parameter
parameterValue = callStmt.getInt(1);
System.out.println("Value returned : " + parameterValue);
I get the following error:
Exception occured in the database
java.sql.SQLException: Missing IN or OUT parameter at index:: 2
Database error code: 17041
As a desperate attempt I also tried to pass Nulls for those parameters. Just included the following line:
callStmt.setNull(2, java.sql.Types.NUMERIC);
I get the following result:
Value returned : 0
That makes sense bcoz setNull supplies SQL Null to the parameter.
I am using Oracle 11g and Oracle 12c Jdbc Driver Version 12.1.0.2.
I don't think there's a simple answer to this question, and that's not because of JDBC, but because of Oracle.
Put simply, the only way I know of calling a procedure and using the default value for a parameter is to not specify the parameter when you call the procedure.
If you are writing
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
you are always specifying both parameters, so you can never use the default value for one of them. If you only want to specify one of them and use the default for the other, write:
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( empCity => ? ) }";
In this case you need to specify the parameter name in the call, as the first parameter is the optional one. If the second parameter was optional instead, the parameter name can be dropped.
Unfortunately, this becomes quite complicated for your real procedure with lots of parameters. What I would do would be to:
Use a StringBuilder to build up the procedure call string.
Run through the parameters, adding paramName => ? parts to it for each parameter you have a value for. Ensure the parts are separated by commas.
Prepare a CallableStatement using the output of the StringBuilder.
Run through the parameters again and call various setString/setInt/setDate/etc. methods on the CallableStatement for each parameter you have a value for.

Issue with COALESCE in DB2 and Jasper Reports

I am having a query wherein I am fetching out sum of a column from a table formed through sub query.
Something in the lines:
select temp.mySum as MySum from (select sum(myColumn) from mySchema.myTable) temp;
However, I don't want MySum to be null when temp.mySum is null. Instead I want MySum to carry string 'value not available' when temp.mySum is null.
Thus I tried to use coalesce in the below manner:
select coalesce(temp.mySum, 'value not available') as MySum from (select sum(myColumn) from mySchema.myTable) temp;
However above query is throwing error message:
Message: The data type, length or value of argument "2" of routine "SYSIBM.COALESCE" is incorrect.
This message is because of datatype incompatibility between argument 1 and 2 of coalesce function as mentioned in the first answer below.
However, I am directly using this query in Jasper to send values to Excel sheet report:
hashmap.put("myQuery", this.myQuery);
JasperReport jasperReportOne = JasperCompileManager.compileReport(this.reportJRXML);
JasperPrint jasperPrintBranchCd = JasperFillManager.fillReport(jasperReportOne , hashmap, con);
jprintList.add(jasperPrintOne);
JRXlsExporter exporterXLS = new JRXlsExporter();
exporterXLS.setParameter(JRExporterParameter.JASPER_PRINT_LIST, jprintList);
exporterXLS.exportReport();
In the excel sheet, I am getting value as null when the value is not available. I want to show 'value unavailable' in the report.
How could this be achieved ?
Thanks for reading!
The arguments to coalesce must be compatible. That's not the case if the first is numeric (as mySum probably is) and the second is a string.
For example, the following PubLib doco has a table indicating compatibility between various types, at least for the DB2 I work with (the mainframe one) - no doubt there are similar restrictions for the iSeries and LUW variants as well.
You can try something like coalesce(temp.mySum, 0) instead or convert the first argument to a string with something like char(). Either of those should work since they make the two arguments compatible.

Use NamedParameterJdbcTemplate to update array field

I have a double precision array field dblArrayFld in a table myTable and I'd like to update it using Spring's NamedParameterJdbcTemplate (I'm using Postgres).
I'm running code like this:
SqlParameterSource params = (new MapSqlParameterSource())
.addValue("myarray", myDblArrayListVar)
.addValue("myid", 123);
namedJdbcTemplate.update("UPDATE myTable SET dblArrayFld = :myarray WHERE idFld = :myid", params);
This returns an error that reads syntax error at or near "$2"
I'm assuming my syntax on :myarray is at fault here. I've also tried encasing :myarray in the following ways:
dblArrayFld={:myarray}
dblArrayFld={ :myarray }
dblArrayFld=[:myarray]
dblArrayFld=ARRAY[:myarray]
dblArrayFld=(:myarray)
What's the correct syntax here?
Wehn you try to bind Collection or array as named parameter, NamedParameterJdbcTemplate explodes the appropriate named parameter in your statement into a number of positional parameters matching the length of your array / collection. This is useful for WHERE column IN (:param) statements, but is not going to work in this case.
In order to set an actual Postgres array you have to supply your parameter as java.sql.Array. You can create its instance using Connection#createArrayOf() method.

Categories

Resources