PantheosMax Posted April 17, 2015 Share Posted April 17, 2015 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/libI created an applicationContext-myDataSource.xml and put it in WEB-INFI created a myCustomDataSource_messages.properties and put it in WEB-INF/bundlesI 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 guidelineDid 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 More sharing options...
elizam Posted April 22, 2015 Share Posted April 22, 2015 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now