I try to create dynamic crosstab. When I try, I have an error java.lang.ClassCastException Jasper Report Crosstab than I solved it. But my report is empty. I don't get it why. I check my result set is empty or not. But it does not empty.
Here is my code:
public class DynamicJasperTemplate{
.....//variables define here
public void buildReport() throws Exception{
....//I create query here and get row column and measure field name
JRDataSource ds = getDataSource(query,a,b,c);//I get data from db as jrdatasource
DynamicReport dr = buildReportLayout(a,b,c,ds); // build report layout and add it crosstab in this method.
params.put("sr",ds);//I set report parameter value
JasperReport jr = DynamicJasperHelper.generateJasperReport(dr, new ClassicLayoutManager(), params);
JasperPrint jp = JasperFillManager.fillReport(jr, params, ds);
JasperExportManager.exportReportToPdfFile(jp,"C:/report-out.pdf");
}
private DynamicReport buildReportLayout(String[] a,String[] b,String[] c, JRDataSource ds) {
FastReportBuilder drb = new FastReportBuilder();
drb.setWhenNoDataAllSectionNoDetail();
initStyles();
CrosstabBuilder cb = new CrosstabBuilder();
cb.setHeight(200)
.setWidth(500)
.setHeaderStyle(mainHeaderStyle)
.setDatasource("sr",DJConstants.DATA_SOURCE_ORIGIN_REPORT_DATASOURCE, DJConstants.DATA_SOURCE_TYPE_JRDATASOURCE)
.setUseFullWidth(true)
.setColorScheme(4)
.setAutomaticTitle(true)
.setCellBorder(Border.PEN_1_POINT());
Object obj="NUMBER";
Object obj1="VARCHAR2";
String type = null;
for(int i=0; i<a.length; i++) {
DJCrosstabRow row = new CrosstabRowBuilder().setProperty(a[i],String.class.getName())
.setHeaderWidth(100).setHeight(0)
.setTitle(a[i])
.setShowTotals(true).setTotalStyle(totalStyle)
.setTotalHeaderStyle(totalHeader).setHeaderStyle(colAndRowHeaderStyle)
.build();
cb.addRow(row);
}
DJCrosstabColumn col =new CrosstabColumnBuilder().setProperty(b.toString(),"java.sql.Timestamp")
.setHeaderHeight(60).setWidth(50)
.setTitle(b.toString()).setShowTotals(true)
.setTotalStyle(totalStyle).setTotalHeaderStyle(totalHeader)
.setHeaderStyle(colAndRowHeaderStyle)
.build();
cb.addColumn(col);
cb.addMeasure(c[0],"java.math.BigDecimal", DJCalculation.NOTHING , c[0],measureStyle);
djcross = cb.build();
drb.addHeaderCrosstab(djcross);
drb.setUseFullPageWidth(true);
drb.addParameter("sr", "java.util.Collection");
DynamicReport dr = drb.build();
return dr;
}
private void initStyles() {
....//here ı define styles
}
private JRDataSource getDataSource(String query,String[] a,String[] b,String[] c) throws SQLException, JRException {
Connection con = new getConnection().conn();
List<Map<String, ?>> arr = new ArrayList<Map<String, ?>>();
String columnValue;
Map data = new HashMap();
JRResultSetDataSource result = null;
ResultSet rs = null;
int i;
try{
if(con!=null){
Statement stmt = con.createStatement();
rs = stmt.executeQuery(query);
JRDataSource ds = new JRResultSetDataSource(rs);
return ds;
}
......
I hope you can tell me the what I make wrong.
I solved my problem here solution :
when ı delete drb.addParameter("sr", "java.util.Collection"); and b.toString() i make error as unknown column change it b[0] than my problem solved.
Related
I use an MYSQL Blob to store an Image inside a Database. Now I want to show the image in my IONIC application in which I also uploaded it.
How it works and how can I store it inside an Object?
You can find my code here:
Java Class
public JSONObject getItems(String email) throws SQLException, ClassNotFoundException, IOException {
JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
Connection conn = new MYSQLAccess().getConnection();
String sql = "SQL String";
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setString(1, email);
ResultSet rs = pstm.executeQuery();
while (rs.next()) {
jsonObject.put("1", rs.getBlob("1"));
jsonObject.put("2",rs.getInt("2"));
jsonObject.put("3", rs.getString("3"));
jsonObject.put("4", rs.getString("4"));
jsonArray.add(performanceCarsJsonObject);
}
jsonObject = new JSONObject();
jsonObject.put("array", jsonArray);
conn.close();
return jsonObject;
}
TypeScript Ionic/ Angualar
getPerformanceCars() {
let params = {"email": this.user.getEmail()};
this.cars.performanceCars(params).then(data => {
this._List = data;
this._List = this._List.value.icons;
this.itemList = this._List;
});
}
Ionic HTML
<ion-list>
<ion-item-sliding *ngFor="let items of itemList">
<button ion-item (click)="openItem(item)">
<ion-avatar item-start>
<img [src]="items.img" />
</ion-avatar>
<h2>{{ items.email }}</h2>
<p>{{ items.values }}</p>
<ion-note item-end *ngIf="items.note">{{ cars.note }}</ion-note>
</button>
</ion-item-sliding>
</ion-list>
The preview of the photo within the IONIC Input Uploader uses the following HTML code.
<div class="profile-image" style="background-image: url("data:image/jpeg;base64,DATA;);"></div>
I hope you can help me, to fix my problem.
Solution
I fixed the problems by creating two new methods. In the first step, I create the getItemBlob Method to extract the Blob outside the database. In the next step, I create the method getItemImage in the controller class. These methods search the correct blob inside the database by the itemID convert the Blob in an InputStream and in the last step inside a ServletOutputStream.
In the HTML part, I used a normal img Tag and mapped the server hostname, port and the getItemImage method together to display the image.
Java Class (Item Services)
public Blob getItemBlob(String id) throws SQLException{
Blob image = null;
Connection conn = new MYSQLAccess().getConnection();
String sql = "SELECT ITEMDATA FROM OWNITEM WHERE OWNITEMID = ? AND ACTIVE = 1";
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setString(1, id);
ResultSet rs = pstm.executeQuery();
while (rs.next()) {
image = rs.getBlob("ITEMDATA");
}
conn.close();
return image;
}
Java Class (Item Controller)
#ResponseBody
#CrossOrigin(origins = "http://localhost:8100")
#RequestMapping(value = "/getItemImage")
public void getItemImage(#RequestParam("id") String id, HttpServletResponse response) throws IOException, SQLException {
ServletOutputStream out = response.getOutputStream();
ItemServices myItemServices = new ItemServices();
Blob image = myItemServices.getItemBlob(id);
response.setContentType("image/jpg");
InputStream in = image.getBinaryStream();
int length = (int)image.length();
int bufferSize = 1920;
byte[] buffer = new byte[bufferSize];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
in.close();
out.flush();
}
Java Class (Subscriber Controller)
#SuppressWarnings("unchecked")
public JSONObject getSubscribersItems(String email) throws SQLException, ClassNotFoundException {
JSONObject subscribersItemsJsonObject = new JSONObject();
JSONArray subscribersItemsJsonArray = new JSONArray();
ArrayList<String> subscribersArrayList = this.getSubscriber(email);
Connection conn = new MYSQLAccess().getConnection();
String sql = "SELECT T1.OWNITEMID,T1.ITEMNAME,T2.USERNAME,T2.COUNTRY FROM OWNITEM T1,CUSTOMER T2 WHERE T1.EMAIL = T2.EMAIL AND T1.EMAIL = ? AND T1.ITEMDATA != 'NULL' AND T2.ACTIVE = 1";
PreparedStatement pstm = conn.prepareStatement(sql);
for (int i = 0; i < subscribersArrayList.size(); i++) {
pstm.setString(1, subscribersArrayList.get(i));
ResultSet rs = pstm.executeQuery();
while (rs.next()) {
subscribersItemsJsonObject = new JSONObject();
subscribersItemsJsonObject.put("itemID", rs.getInt("OWNITEMID"));
subscribersItemsJsonObject.put("itemName", rs.getString("ITEMNAME"));
subscribersItemsJsonObject.put("username", rs.getString("USERNAME"));
subscribersItemsJsonObject.put("country", rs.getString("COUNTRY"));
subscribersItemsJsonArray.add(subscribersItemsJsonObject);
}
}
subscribersItemsJsonObject = new JSONObject();
subscribersItemsJsonObject.put("items", subscribersItemsJsonArray);
conn.close();
return subscribersItemsJsonObject;
}
IONIC HTML
<ion-list>
<ion-item-sliding *ngFor="let items of subscriberItemsItemList">
<button ion-item (click)="openItems(items)">
<ion-avatar item-start>
<img src="{{ itemImageUrl }}/getItemImage?id={{ cars.itemID }}" />
</ion-avatar>
<h2>{{ items.username }}</h2>
<p>{{ items.country }}</p>
<ion-note item-end *ngIf="items.note">{{ items.note }}</ion-note>
</button>
</ion-item-sliding>
</ion-list>
IONIC TypeScript/ Angular
getDesignCars() {
let params = {"email": this.user.getEmail()};
this.cars.homeCars(params).then(data => {
this._subscriberCarsList = data;
this._subscriberCarsList = this._subscriberCarsList.value.cars;
this.subscriberCarsItemList = this._subscriberCarsList;
});
}
On tomcat, I have a class that return a list of objects from the database, something like this:
List<Entity> list = null;
Connection con = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
con = Connector.getConexion();
String sql = "SELECT * FROM some_table LIMIT 10;";
pstm = con.prepareStatement(sql);
rs = pstm.executeQuery();
list = new ArrayList<>();
EntityCrimesChicago ecc = null;
while (rs.next()) {
e = new Entity();
e.setID(rs.getString(1));
e.setCase_Number(rs.getString(2));
list.add(e);
}
return list;
catch { ... }
finally { ... }
The entity and table have all fields as String/varchar, even the ID.
The service gets the list with (this is a web method):
public List<Entity> someThing(String q) {
DAOThings controller = new DAOThings();
List<Entity> things = controller.getSomeThings(Integer.parseInt(q));
return things;
}
This return
java.io.IOException: No serializer found for class Entity in registry org.apache.axis.encoding.TypeMappingDelegate#26a0e5e4
But, If I change the web method to return a String and I use return things.toString(); that return the objects, but doesn't the his content.
What can I do to return the list correctly?
I try returning a manueally added string list and works fine.
I solve my problem passing the object to a String array.
When I get the object list:
public List<Entity> someThing(String q) {
DAOThings controller = new DAOThings();
List<Entity> things = controller.getSomeThings(Integer.parseInt(q));
return things;
}
I only need to do this:
public List<String[]> someThing(String q) {
DAOThings controller = new DAOThings();
List<Entity> things = controller.getSomeThings(Integer.parseInt(q));
List<String[]> list = new ArrayList<>;
for (Entity value : things) {
String[] array = new String[obj_fields];
array[0] = value.getAny();
...
array[n] = value.getAny();
list.add(array);
}
return list;
}
And Apache Axis does the magic.
I have written the following code
MapSqlParameterSource in = new MapSqlParameterSource();
in.addValue("V_OPP_ID", bean.getOpportunityId());
in.addValue("V_NAME",bean.getName());
in.addValue("V_FROM_DATE", bean.getStdate());
in.addValue("V_TO_DATE", bean.getEddate());
in.addValue("V_USERTYPE", bean.getUserType());
jdbcCall.execute(in);
Here the jdbcCall.execute(in) returns me resultset/table corresponding to Arraylist. How do i extract this ArrayList
Is using jdbcCall a correct Approach ? If not what is Adviced ?
This is the code I use for a call to a function:
RowMapper<String> rm = new ParameterizedRowMapper<String>() {
#Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
};
myStoredProcedure = new SimpleJdbcCall(DataSourceConnection.getDataSource())
.withCatalogName("PACKAGE")
.withFunctionName("GET_ALIAS")
.returningResultSet("return", rm);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("P_ID",userStr);
params.addValue("P_DOMAIN_ALIAS", domain[0]);
List<String> list = myStoredProcedure.executeFunction(List.class,params);
and if you are not able to use the metadata then this is the code:
RowMapper<String> rm = new ParameterizedRowMapper<String>() {
#Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
};
SqlParameter emailParam = new SqlParameter("P_ID", OracleTypes.VARCHAR);
SqlParameter domainParam = new SqlParameter("P_DOMAIN_ALIAS", OracleTypes.VARCHAR);
SqlOutParameter resultParam = new SqlOutParameter("return", OracleTypes.CURSOR);
myStoredProcedure = new SimpleJdbcCall(DataSourceConnection.getDataSource())
.withCatalogName("PACKAGE")
.withFunctionName("GET_ALIAS")
.withoutProcedureColumnMetaDataAccess()
.returningResultSet("return", rm)
.declareParameters(resultParam, emailParam, domainParam);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("P_ID",userStr);
params.addValue("P_DOMAIN_ALIAS", domain[0]);
List<String> list = myStoredProcedure.executeFunction(List.class,params);
I am trying to find an easy way to deal with Stored Procedures / SQL returning multiple result sets. I have been using the SimpleJdbcOperations#queryForList() method however this will only return the first result set as a List<Map<String, Object>>. I need to be able to get multiple result sets, ideally as a Collection of List<Map<String, Object>> or something. The program I am writing is a middleware component so I don't know what the SQL will be, or the form of the result set.
I think I have to use the JdbcOperations class which gives me access to more methods, including execute(CallableStatementCreator csc, CallableStatementCallback<T> action) but now I am stuck.
CallableStatementCallback<T> callback = new CallableStatementCallback<T>() {
#Override
public T doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException
{
boolean results = cs.execute(request);
while(results)
{
ResultSet result = cs.getResultSet();
results = cs.getMoreResults();
}
return null;
}
};
I am not really sure how to use the method though, or what to do with the ResultSet to get my generic List<Map<String, Object>>s.
I managed to get a Set<ResultSet> using this code,
private Set<ResultSet> executeProcedure(final String sql)
{
return jdbc.execute(new CallableStatementCreator() {
#Override
public CallableStatement createCallableStatement(Connection con) throws SQLException
{
return con.prepareCall(sql);
}
}, new CallableStatementCallback<Set<ResultSet>>() {
#Override
public Set<ResultSet> doInCallableStatement(CallableStatement cs) throws SQLException
{
Set<ResultSet> results = new HashSet<>();
boolean resultsAvailable = cs.execute();
while (resultsAvailable)
{
results.add(cs.getResultSet());
resultsAvailable = cs.getMoreResults();
}
return results;
}
});
}
Just going to look at translating a ResultSet into List<Map<String, Object>>.
You can use the resultSet.getMetaData() method to work out what columns are in the data:
ResultSetMetaData meta = resultSet.getMetaData();
int colcount = meta.getColumnCount();
for (int i = 1; i <= colcount; i++)
{
String name = meta.getColumnLabel(i); // This is the name of the column
int type = meta.getColumnType(i); // from java.sql.Types
// Maybe add to a Map,List, etc...
}
You can then do as the other commentors have mentioned do a loop through the ResultSet pulling out the data you need:
while (resultSet.hasNext())
{
resultSet.next();
// Find the columns you want to extract (via the above method maybe) and add to your row.
}
This code might be easier to use in most cases:
Map<String,Object> resultSets = new JdbcTemplate(dataSource)
.call(con -> con.prepareCall(query), new ArrayList<>());
I have used below method to get List of ResultSet in form of List<Map<String, Object>>
public List<List<Map<String, Object>>> executeProcedure(final String sql) {
return jdbcTemplate.execute(new CallableStatementCreator() {
#Override
public CallableStatement createCallableStatement(Connection con) throws SQLException {
return con.prepareCall(sql);
}
}, new CallableStatementCallback<List<List<Map<String, Object>>>>() {
#Override
public List<List<Map<String, Object>>> doInCallableStatement(CallableStatement cs) throws SQLException {
boolean resultsAvailable = cs.execute();
List<List<Map<String, Object>>> list = new ArrayList<List<Map<String, Object>>>();
while (resultsAvailable) {
ResultSet resultSet = cs.getResultSet();
List<Map<String, Object>> subList = new ArrayList<Map<String, Object>>();
while (resultSet.next()) {
ResultSetMetaData meta = resultSet.getMetaData();
int colcount = meta.getColumnCount();
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 1; i <= colcount; i++) {
String name = meta.getColumnLabel(i);
map.put(name, resultSet.getString(i));
}
subList.add(map);
}
list.add(subList);
resultsAvailable = cs.getMoreResults();
}
return list;
}
});
}
I am trying to create JR report which is taking start_date and end_date as parameters.
The query:
SELECT * FROM emp WHERE joining_date BETWEEN $P{frm_date} AND $P{to_date}
The code:
Date from_date = dt_from_date.getDate();
Date to_date = dt_to_date.getDate();
java.sql.Date frm_dte = new java.sql.Date(from_date.getTime());
java.sql.Date to_dte = new java.sql.Date(to_date.getTime());
try {
HashMap map = new HashMap();
map.put("$P{frm_date}", frm_dte);
map.put("$P{to_date}", to_dte);
JasperPrint jp = JasperFillManager.fillReport(is, map, con);
JRViewer jv = new JRViewer(jp);
JFrame jf = new JFrame();
jf.getContentPane().add(jv);
jf.validate();
jf.setVisible(true);
jf.setSize(new Dimension(800, 600));
jf.setLocation(300, 100);
jf.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
} catch (JRException ex) {
ex.printStackTrace();
}
Can we pass Two Parameters to same Column in the table? Eg:
map.put("joining_date", frm_dte);
map.put("joining_date", to_dte);
You can pass date as string format type as follow,
if(from_date!=null)
{
formattedEndDate=new SimpleDateFormat("yyyy-MM-dd").format(from_date);
}
if(getStartDate()!=null)
{
formattedStartDate=new SimpleDateFormat("yyyy-MM-dd").format(to_date);
}
Your code is wrong.
You should pass parameters as below:
Map<String, Object> map = new HashMap<String, Object>();
map.put("frm_date", frm_dte);
map.put("to_date", to_dte);
You don't need to add P${} to the parameter's name.
There are a lot of samples in JasperReports distribution package.
You can look at this sample for more details.
private JasperPrint generateReport() {
Connection conn = null;
JasperPrint myJPrint = null;
try {
conn =yourconnectionName;
// parameters to be passed to the report
Map<String, Object> params = new HashMap();
// Loading my jasper file
JasperDesign jasperDesign = null;
JasperReport jasperReport = null;
params.put("REPORT_DIR",yourClassName.class.getClassLoader()
.getResource("yourJasperFileName.jrxml").toString().replace("yourJasperFileName.jrxml", ""));
jasperDesign = JasperManager.loadXmlDesign(yourClassName.class
.getClassLoader().getResourceAsStream("yourJasperFileName.jrxml"));
params.put("joining_date", frm_dte);
params.put("leaving_date", frm_dte);
jasperReport = JasperCompileManager.compileReport(jasperDesign);
/*
* Filling the report with data from the database based on the
* parameters passed.
*/
myJPrint = JasperFillManager.fillReport(jasperReport, params, conn);
params.clear();
} catch (JRException ex) {
ex.printStackTrace();
}
return myJPrint;
}