Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » Feedback from Standalone Client Implementation
Feedback from Standalone Client Implementation [message #1116016] Tue, 24 September 2013 18:24 Go to next message
Chris Monty is currently offline Chris Monty
Messages: 18
Registered: July 2013
Junior Member
I just completed a small standalone project which in essence, runs as a desktop application. Jeramie mentioned that feedback would be welcome, so here it is.

Features:
  • Single user, no authentication, no server (offline implementation)
    Since this is a desktop application, a server is unnecessary.
  • Custom DB driver (Derby v 10.10.1.1)
    I chose Derby because it's portable and stand-alone (no db installation required). I chose version 10.10.1.1 because it supports sequences. I bundled the derby database folder in with the client .zip. Installation is as simple as download, unzip and run.
  • Jasper Reports integration
    Because the ReportingService shares its connection with the Jasper reporting engine, it's possible to create reports from a database (like Derby) which only supports a single connection.
  • Docx4j integration
    Just for 'screen scraping' tables into an Excel document.

I had some trouble creating my own derby jdbc connector bundle, even with the help of the tutorial. Most of my time was spent here resolving package import problems. I think that for making your own jdbc bundle you a) have to be well versed with eclipse plugin project architecture, or b) will be by the time you get it working.

Once the whole thing compiled, I faced some issues with the new Sql Style. I had copied the old DerbySqlStyle.java and AbstractDerbySqlService.java, but was having problems with decimals. It seems in Derby, decimal values are typed as java.sql.Types.DOUBLE. The default implementation of
org.eclipse.scout.rt.server.services.common.jdbc.style.AbstractSqlStyle.writeBind()
supports only DECIMAL and NUMERIC, and refers DOUBLE types to writeDefaultBind() which truncates decimals.

My ugly-but-functional fix is to subclass AbstractSqlStyle and override writeBind() as so:
  @Override
	public void writeBind(PreparedStatement ps, int jdbcBindIndex, SqlBind bind)
			throws SQLException {
	  switch (bind.getSqlType()) {
	  case Types.DOUBLE:
		  // explicit handling for DOUBLE types. The default DOUBLE handling from AbstractSQLService
		  // does not explicitly specify a scale. 
		  if (bind.getValue() instanceof Double) {
			  Double value = ((Double)bind.getValue());
			  // figure out the scale by counting the number of digits after the decimal point
			  String strVal = value.toString();
			  int decimalIndex = strVal.indexOf('.');
			  int scale = (decimalIndex > 0)?(strVal.length() - decimalIndex - 1):0;
			  // I never need more than 3 decimal places.
			  if (scale > 3) {
				  scale = 3;
			  }
			  ps.setObject(jdbcBindIndex, value, bind.getSqlType(), scale);
		  }
		  break;
		  default:
			  super.writeBind(ps, jdbcBindIndex, bind);
	  }
	}


I realised at installation test that my application runs only on 64-bit Windows (not 32-bit). This surprised me, being Java and all. My development environment is 64-bit, as is my version of Java 7. Does anyone know how to remove this constraint?

One final snag I hit was with my Jasper report, which I implemented according to this tutorial. I have a report which has a sub-report. I'm able to load the report as a ByteArrayInputStream, but the report then tries to load the sub-report itself, which it can't find of course. To make matters worse, the report location in my deployment build is inside the plugins folder, which takes on a dynamic name. I've worked around this by making a configuration key with a value like
.\\plugins\\<packagename>_<version>.<timestamp>\\reports\\
which gets passed into the report as a parameter (I have to manually update this after each deploy) but it's hardly elegant. Does anyone know how I might find the reports folder at runtime?

But otherwise it's a nice little desktop app.
Re: Feedback from Standalone Client Implementation [message #1116479 is a reply to message #1116016] Wed, 25 September 2013 10:01 Go to previous messageGo to next message
Nils Israel is currently offline Nils Israel
Messages: 23
Registered: May 2010
Junior Member
Hi Chris,
it is possible to load the subreport the same way as the master report and add the compiled subreport as a parameter:

@Override
  public byte[] createCompanyReport(Long companyID) throws ProcessingException {
    JasperPrint jasperPrint;
    // create a map to pass parameters to the report
    HashMap<String, Object> parameter = new HashMap<String, Object>();
    parameter.put("COMPANY_NR", companyID);
    try {
      // load the report from the reports plugin
      URL url = new URL("platform:/plugin/org.eclipse.scout.minicrm.reports/reports/company.jrxml");
      InputStream inputStream = url.openConnection().getInputStream();
      // compile the report
      JasperReport report = JasperCompileManager.compileReport(inputStream);

      // load the subreport from the reports plugin
      URL urlSubreport = new URL("platform:/plugin/org.eclipse.scout.minicrm.reports/reports/subreport.jrxml");
      InputStream inputStreamSubreport = urlSubreport.openConnection().getInputStream();
      // compile the subreport
      JasperReport subreport = JasperCompileManager.compileReport(inputStreamSubreport);
      parameter.put("mySubreport", subreport);

      // let Jasper Reports use our already defined SQL Connection
      jasperPrint = JasperFillManager.fillReport(report, parameter, SQL.getConnection());
      // don't create a file but let jasper put the contents in an byte array
      ByteArrayOutputStream ba = new ByteArrayOutputStream();
      JasperExportManager.exportReportToPdfStream(jasperPrint, ba);
      // return the contents to the caller
      return ba.toByteArray();
    }
    catch (JRException e) {
      throw new ProcessingException("An error occured during the creation of the report.", e);
    }
    catch (MalformedURLException e) {
      throw new ProcessingException("Can't load the report file.", e);
    }
    catch (IOException e) {
      throw new ProcessingException("An IO-error occured while reading the report file.", e);
    }
  }


To use the subreport you have to add the parameter
<parameter name="mySubreport" class="net.sf.jasperreports.engine.JasperReport"/>

to the master report and and replace the subreportExpression
<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{mySubreport}]]></subreportExpression>


Kind regards,
Nils
Re: Feedback from Standalone Client Implementation [message #1116673 is a reply to message #1116479] Wed, 25 September 2013 14:33 Go to previous messageGo to next message
Chris Monty is currently offline Chris Monty
Messages: 18
Registered: July 2013
Junior Member
Nils, that worked a charm. Thanks for the tip.
Re: Feedback from Standalone Client Implementation [message #1117095 is a reply to message #1116016] Thu, 26 September 2013 01:07 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie Bresson
Messages: 385
Registered: October 2011
Senior Member
Chris Monty wrote on Wed, 25 September 2013 00:24
I realised at installation test that my application runs only on 64-bit Windows (not 32-bit). This surprised me, being Java and all. My development environment is 64-bit, as is my version of Java 7. Does anyone know how to remove this constraint?


How are you building your application?
- Manually: Export wizard from the Scout Perspective?
- Manually: Export from the Eclipse Product Editor?
- PDE Build?
- Maven Build?

Do you have exported the JRE with your application?
Re: Feedback from Standalone Client Implementation [message #1119365 is a reply to message #1117095] Sat, 28 September 2013 07:07 Go to previous message
Chris Monty is currently offline Chris Monty
Messages: 18
Registered: July 2013
Junior Member
Hi Jeremie, thanks for the response.
Until now I was using the Scout export wizard which automagically does everything. But now that you've asked, I also discovered the Eclipse product export wizard and tried it. I found a tutorial about Products and Deployment, which was helpful.

I tried rewinding the jre from JavaSE-1.7 to JavaSE-1.6 - just in case it was my x64 installation Java 7. I found that when exporting a jre with the application, java rejects all but 64-bit versions with an error message on startup: Quote:
Failed to load the JNI shared Library (...JDK)

Searches on stackoverflow indicate this might lie with the version of eclipse I'm using. Is there a way to generate a 32-bit compatible application, or should I try installing a 32-bit of Eclipse? Or should I look to Maven or PDE for a solution?
Previous Topic:How to run/debug scout SDK from source?
Next Topic:Best practices for different client types?
Goto Forum:
  


Current Time: Mon Oct 07 23:34:44 EDT 2013

Powered by FUDForum. Page generated in 0.01854 seconds