Jump to content
We've recently updated our Privacy Statement, available here ×

How to deploy a Custom Data Source to Jasperreports Server 6?


PantheosMax

Recommended Posts

Hi everyone,

sadly, i stil fail to deploy my Custom Data Source to our Jasperreports Server.

What i did:

I wrote an implementation of ReportDataSourceService in Java (7), that creates an implementation of JRDataSource. Added JasperReports Library + JasperServer API as external jars. Compiled as myCustomDataSource.jar nad put in WEB-INF/lib

I created an applicationContext-myDataSource.xml and put it in WEB-INF

I created  a myCustomDataSource_messages.properties and put it in WEB-INF/bundles

I added "myQueryLanguage" as a "queryLanguage" property to WEB-INF/flows/queryBeans.xml (although i dont have a QueryExecuter implementation yet, but just in case)

When i try to add a DataSource to my Server, the page just doesnt load anymore and -nothing- at all happens. No dialog at all, cant even create standard Data Sources.

I'm, using Jaspersoft Ultimate Guide as a guideline

Did that happen to anyone else? Can anybody point to a good ressource detailing the deployment process and / or examples?

Will provide code if needed, just don't want to make the post too long

 

Thx in advance,

Stefan

Link to comment
Share on other sites

  • Replies 1
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

There was a change in the Spring configuration for JR server 6.0 which changes how some of the existing Spring beans are made accessible for use by other beans. This can break existing custom data sources. This change specifically affects beans which implement the interface ReportDataSourceServiceFactory. Prior to 6.0, if code in JR server accessed a bean of this type, it would get the actual instance of the Spring bean as configured in the Spring XML file, and it could be cast to the concrete class.

In 6.0 and later, these beans were intercepted in order to implement the profile attributes feature, and instead of seeing the actual instance, other code would see a dynamic proxy instead of the actual bean. Dynamic proxies are a Java feature which allows classes to be generated at runtime which implement any interface that can be loaded on the classpath. The resulting object can be cast to any of those interfaces, but doesn't correspond to any concrete class. There's plenty of info on the web about these, but here's one link:

http://www.javaworld.com/article/2076233/java-se/explore-the-dynamic-proxy-api.html

Since proxies can only represent interfaces, existing code that tries to cast the bean to a concrete class will break. Casting is usually done to get access to methods on a more specific class or interface. As long as the code is not casting the bean to a concrete class, it will work, so there are two ways to get around this problem: - If the code needs to access methods on an existing interface, just do a cast to that interface, or inject the property using the existing interface, so no cast is needed. - If the code needs to access methods that are not on an existing interface, simply create an interface with the methods needed, and have the target object implement that interface. For example, let's say you have a bean with id "myBean" that needs to access the jdbcDataSourceServiceFactory, configured like this:

<bean id="jdbcDataSourceServiceFactory"class="com.jaspersoft.jasperserver.api.engine.jasperreports.service.impl.JdbcReportDataSourceServiceFactory">...</bean>myBean has a Spring config like this:<bean id="myBean" class="example.MyBean">    <property name="jdbcDSSF" ref="jdbcDataSourceServiceFactory"/>...Code like this will break:public class MyBean {  private ReportDataSourceServiceFactory jdbcDSSF;  public ReportDataSourceServiceFactory getJdbcDSSF() {    return jdbcDSSF;  }  // before 6.0, was called by Spring with the actual bean  // 6.0 and after, is called with a dynamic proxy  public void setJdbcDSSF(ReportDataSourceServiceFactory jdbcDSSF) {    this.jdbcDSSF = jdbcDSSF;  }  public void doSomething() {    // this code used to work, but now it will break    ((JdbcReportDataSourceServiceFactory) jdbcDSSF).createService();    ((JdbcReportDataSourceServiceFactory) jdbcDSSF).doSomethingElse();  }}Since the first call is a method which is part of theReportDataSourceServiceFactory, the cast is unnecessary; to fix it, just leaveit out:    jdbcDSSF.createService();We are pretending that JdbcReportDataSourceServiceFactory has a method calleddoSomethingElse(); this method is not part of any interface, but you can createan interface that includes it:public interface MyDSSF extends ReportDataSourceServiceFactory {   public void doSomethingElse();}JdbcReportDataSourceServiceFactory would need modification so that itimplements this new interface:public JdbcReportDataSourceServiceFactory implements MyDSSF {....}You don't have to change the declaration in MyBean because Spring will generatea dynamic proxy implementing MyDSSF, but if you change the declaration, thecode will be easier to understand because no casts will be necessary:public class MyBean {  private MyDSSF jdbcDSSF;  public MyDSSF getJdbcDSSF() {    return jdbcDSSF;  }  // called with a dynamic proxy which implements all needed interfaces  public void setJdbcDSSF(MyDSSF jdbcDSSF) {    this.jdbcDSSF = jdbcDSSF;  }  public void doSomething() {    // no need to cast    jdbcDSSF.createService();    jdbcDSSF.doSomethingElse();  }}[/code]
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...