(Dynamic Jasper Reports) Importing parameters from a custom .jrxml fil - templates

I'm developing a Java project with JasperReports(v.4.0.6) and DynamicJasperReports(v.4.0.1). I have generated a custom .jrxml with the most recent iReport plugin for Eclipse.
In my .jrxml report, I define two parameters which will be filled by the Java program according to some input given by the user.
<parameter name="ReportTitle" class="java.lang.String"/>
<parameter name="DataFile" class="java.lang.String"/>
Then, as this tutorial states, and since I want to maintain a couple of parameters predefined, I invoke the setTemplate() method from my code.
String table_template = "report_templates/TableTemplate.jrxml";
Map<String, String> params;
...
DynamicReportBuilder drb = new DynamicReportBuilder();
drb.setTemplateFile(table_template, true, true, true, true);
DynamicReport dr = drb.build();
I pass the parameters to the template doing the following:
params.put("ReportTitle", "CustomTitle");
params.put("DataFile", "CustomSubtitle");
However, when I genereate de report, these two fields appear blank, as if the DJ library hadn't save the places in which to insert the values beforehand. I don't get any other errors or exceptions.
I've tried downgrading the Jasper library to al older version, but to no avail either.
I'd appreciate if someone could give me some insight to what I am doing wrong.
Thanks in advance.

Having a paremeter already defined in the jrxml only means that in your custom expression you can get its value as
params.get("paramName")
Without prior registration ( drb.addParameter(...) )
You can always create a custom expression column and put a breakoint in the custom expression code and check the contents of the parameters map in runtime!
If you use the paremter outside DJ, say, a header or footer text, there should be not problem with it

Related

How to automate M2Doc generation including the settings?

I've applied the guidance on programmatic usage of M2Doc (also with this help) to successfully generate a document via the API, which was previously prepared by using the M2Doc GUI (configured .docx plus a .genconf file). It seems to also work with a configured .docx, but without a .genconf file.
Now I would like to go a step further and ease the user interface in our application. The user should come with a .docx, include the {m:...} fields there, especially for variable definition, and then in our Eclipse application just assign model elements to the list of variables. Finally press "generate". The rest I would like to handle via the M2Doc API:
Get list of variables from the .docx
Tell M2Doc the variable objects (and their types and other required information, if that is separately necessary)
Provide M2Doc with sufficient information to handle AQL expressions like projectmodel::PJDiagram.allInstances() in the Word fields
I tried to analyse the M2Doc source code for this, but have some questions to achieve the goal:
The parse/generate API does not create any config information into the .docx or .genconf files, right? What would be the API to at least generate the .docx config information?
The source code mentions "if you are using a Generation" - what is meant with that? The use of a .genconf file (which seems to be optional for the generate API)?
Where can I get the list of variables from, which M2Doc found in a .docx (during parse?), so that I can present it to the user for Object (Model Element) assignment?
Do I have to tell M2Doc the types of the variables, and in which resource file they are located, besides handing over the variable objects? My guess is no, as using a blank .docx file without any M2Doc information stored also worked for the variables themselves (not for any additional AQL expressions using other types, or .oclAsType() type castings).
How can I provide M2Doc with the types information for the AQL expressions mentioned above, which I normally tell it via the nsURI configuration? I handed over the complete resourceSet of my application, but that doesn't seem to be enough.
Any help would be very much appreciated!
To give you an impression of my code so far, see below - note that it's actually Javascript instead of Java, as our application has a built-in JS-Java interface.
//=================== PARSING OF THE DOCUMENT ==============================
var templateURIString = "file:///.../templateReqs.docx";
var templateURI = URI.createURI(templateURIString);
// canNOT be empty, as we get nullpointer exceptions otherwise
var options = {"TemplateURI":templateURIString};
var exceptions = new java.util.ArrayList();
var resourceSetForModels = ...; //here our application's resource set for the whole model is used, instead of M2Doc "createResourceSetForModels" - works for the moment, but not sure if some services linking is not working
var queryEnvironment = m2doc.M2DocUtils.getQueryEnvironment(resourceSetForModels, templateURI, options);
var classProvider = m2doc.M2DocPlugin.getClassProvider();
// empty Monitor for the moment
var monitor = new BasicMonitor();
var template = m2doc.M2DocUtils.parse(resourceSetForModels.getURIConverter(), templateURI, queryEnvironment, classProvider, monitor);
// =================== GENERATION OF THE DOCUMENT ==============================
var outputURIString = "file:///.../templateReqs.autogenerated.docx";
var outputURI = URI.createURI(outputURIString);
variables["myVar1"] = ...; // assigment of objects...
m2doc.M2DocUtils.generate(template, queryEnvironment, variables, resourceSetForModels, outputURI, monitor);
Thanks!
No the API used to parse an generate don't modifies the template file nor the .genconf file. To modify the configuration of the template you will need to use the
TemplateCustomProperties class. That will allow you to register your metamodels and service classes. This instormation is then used to configure the IQueryEnvironment, so you might also want to directly configure the IQueryEnvironment in your code.
The generation in this context referes to the .genconf file. Note The genconf file is also an EMF model, so you can also craft one in memory to launch you generation if it's easier for you. But yes the use of a .genconf file is optional like in your code example.
To the list of variables in the template you can use the class TemplateCustomProperties:
TemplateCustomProperties.getVariables() will list the variables that are declared with their type
TemplateCustomProperties.getMissingVariables() to list varaibles that are used in the template but not declared
You can also find le list of used metamodels (EPackage nsURIs) and imported services classes.
The type of variables is not needed at generation time, it's only needed if you want to validate your template. At generation time you need to pass a map from the variable name to its value as you did in your example. The value of a variable can be a any object from your model (an EObject), a String, an Integer, ... If you want to use something like oclIsKindOf(pkg::MyEClass) you will need to register the nsURI of pkg first see the next point.
The code you provided should let you use something like projectmodel::PJDiagram.allInstances(). This service needs a ResourceSetRootEObjectProvider() that is initialized in M2DocUtils.getQueryEnvironment(). But you need to declare the nsURI of your metamodel in your template (see TemplateCustomProperties). This will register it in the IQueryEnvironment. You can also register it yourself using IQueryEnvironment.registerEPackage().
This should help you finding the missing parts in the configuration of the AQL environment. Your code seems good and should work when you add the configuration part.

How to install feature based on the property set in custom action?

I am trying to install one from two features based on the value that should be set inside of the custom action.
Firstly, I set the value of a property:
UINT __stdcall ConfigurationCheckAction(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_INSTALL_FAILURE;
hr = WcaInitialize(hInstall, "ConfigurationCheckAction");
if (condition) {
MsiSetProperty( hInstall, TEXT("STREAM"), TEXT("RED") );
}
else {
MsiSetProperty( hInstall, TEXT("STREAM"), TEXT("BLUE") );
}
return WcaFinalize(er);
}
Secondly, I make two conditions per two features:
<Feature Id='Complete' Level='1'>
<Feature Id="Red" ConfigurableDirectory="TARGETDIR" Title="F1" Level="0">
<Condition Level="1">STREAM</Condition>
</Feature>
<Feature Id="Blue" ConfigurableDirectory="TARGETDIR" Title="F2" Level="0">
<Condition Level="1">NOT STREAM</Condition>
</Feature>
</Feature>
Note that I don't define property inside of the wxs file previously, as I would like to set it from the custom action.
My custom action is called before InstallInitialize and Execute is immediate.
From the installation log I have confirmation that the property is set.
However, my conditional installation does not work, as it seems like what is in the condition is always evaluated as false.
I tried evaluating conditions:
STREAM, STREAM=RED, STREAM="RED", < ![CDATA[STREAM=RED]]>
I am running out of ideas what to do and would appreciate help.
Too late to test all of this, but here goes with some information. I will check back tomorrow. Essentially I think the problem is your custom action sequencing. Try before Costing.
Some things to consider:
Custom action sequencing: you need to sequence your custom action right and it needs to be present in both silent and interactive installation modes.
Did you try to sequence the set property custom action before CostInitialize? You state you set it before InstallInitialize, but try it before CostInitialize instead (you might have tried).
And did you remember to insert this custom action in the InstallUISequence as well as the InstallExecuteSequence? You need to insert in both sequences in case the setup runs in silent mode. Before CostInitialize in both sequences I believe.
Feature Level: manipulating features via the feature level and INSTALLLEVEL is just one way to do feature control, you can also set features via the command line or using a custom action.
Setting a feature level to 0 should hide the feature from view in the setup's custom dialog.
Setting a feature level higher than the setup's INSTALLLEVEL will deselect the feature from installation.
And the other way around setting a feature level lower or equal to the setup's INSTALLLEVEL will select the feature for installation.
The conditional syntax allowed is quite flexible, and could provide the functionality you need outright - but I have never used them properly. Here is an example from the Installshield forum.
ADDLOCAL & REMOVE: you can manipulate the feature selection by changing the values of the ADDLOCAL and REMOVE properties from a custom action (technically also REINSTALL and ADVERTISE) - and these properties can be set via the command line as well.
Win32: you can also use the Win32 functions MsiGetFeatureState and MsiSetFeatureState - from a C++ custom action - to set feature selection.
Frankly it is a bit mad the whole thing. Also keep in mind that there are feature action states (what is going to happen to a feature) and feature installed states (what state it is in). The Win32 function documentation should explain.
Cross-linking for easy retrieval:
Unselected Feature Being Installed
I have done something similar, but we ended up controlling this at a component level(adding the condition to the <Component/> elements instead of the feature element using a transform during heat). But our condition utilizes CDATA while also using double quotes for the value, which you don't list in what you've tried. So first I'd try the following conditions in your features:
<Condition><![CDATA[STREAM="RED"]]></Condition>
<Condition><![CDATA[STREAM="BLUE"]]></Condition>
If that still does not work, I would try the following:
Add the STREAM property with a default value to your WiX. Then test it with that default value to see if having the default value set to begin with makes it work. That could mean you need to set the property sooner, possibly off a UI event. <Property Id="STREAM" Value="RED"/>
As a last resort, you could add the conditions to each component as I did, but we only did that for very specific reasons, hopefully you can get the conditional feature to work with the above suggestions!
I hope the above fixes your problem, or at least leads you to the answer!
Thank you for your replies. In the end, a combination of your suggestions helped me.
I want to state what did and what did not work:
Adding property to WiX with a default value was not necessary (as well with adding property of this property Secure='yes')
Calling custom action before CostInitialize did not solve the problem on its own, but I believe it was one of the factors that resolved an issue.
Conditional sintax was corrected by:
a) Putting condition inside of CDATA and adding quotes to the value of property as suggested: <Condition><![CDATA[STREAM="RED"]]></Condition>
b) Reversing condition levels so feature has condition level 1 and condition has level 0. This means that feature is always installed, unless the condition expression is false.
Concerning the correct order of the custom actions, the description of the custom action type 51 contains the decisive hint:
"To affect a property used in a condition on a component or feature, the custom action must come before the CostFinalize action in the action sequence."

How to get the full name of a Sitecore DMS rule?

I'm using Sitecore. I want to get the full name/description of a DMS rule in programcode by Sitecore ID, for example: "Where the DayOfWeek has a value that is equal to Tuesday".
Who knows how to do this?
Thanks a lot.
Jordy
I don't know of a simple way, but the class responsible for rendering the rule text is Sitecore.Shell.Applications.Rules.RulesRenderer in Sitecore.Client.dll.
Its constructor accepts the XML from a rules field and you call the Render method, passing in a prepared HtmlTexteWriter. It also has a bunch of fairly self-explanatory private methods like RenderRule, RenderCondition etc.
I'm sure if you decompile that class you can pick out the bits you need.

Getting error while reading salesforce custom field type Rich Textarea

I am using salesforce.cfc (downloded from Riaforge) to integrate coldfusion with salesforce.
<cfset latestProductList = salesforce.queryObject("SELECT Id, Name, Description__c, Price__c, ProductImage__c FROM Product__c") />
I have created one custom object named "Product__c". This object have one custom field "ProductImage__c" type "Rich TextArea". When i an trying to get product without this custom field it is run, but when i am trying to get product with this field i am getting below error:
"INVALID_FIELD: Name, Description__c, Price__c, ProductImage__c FROM Product__c ^ ERROR at Row:1:Column:44 No such column 'ProductImage__c' on entity 'Product__c'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. "
But i have this field. attached screen image of salesforce below.
Thanks,
Arun
A quick look at Salesforce CFC shows that it hasn't been updated in a while. The file SalesForce.cfc is pointing at:
https://www.salesforce.com/services/Soap/u/11.1
That's version 11.1 of the API, which is quite old and is long before rich text fields came into existence.
You might be able to fix this issue by simply updating the reference in SalesForce.cfc to the latest version of the API by changing
https://www.salesforce.com/services/Soap/u/11.1
to
https://www.salesforce.com/services/Soap/u/28.0
in that file, although there's a pretty good likelihood that that will break something else, since version 28.0 will have lots of new stuff that SalesForce.cfc is not coded to handle.
In any case, your problem is in fact the API version that you're using. In cases like this, when a field type did not exist as of a certain API version, then that field is invisible for that version. In your case, your rich text field is invisible for your API version, 11.1.

Using Type-safe URLs with setMessage? (shamlet versus hamlet)

How do I use a type-safe url with setMessage?
I want to change
...
setMessage [shamlet|<span .warning>Warning! See Help.|]
...
to a message that contains a link.
From what I could gather thus far, it ought to work somehow like this
...
renderer <- getUrlRender
let html = [hamlet|<span .warning>Warning! See #
<a href=#{HelpR}> Help!|]
setMessage $ toHtml $ html renderer
...
but that code just gives me confusing error messages all over the file.
I did read the printed Yesod Book Chapter on Shakespearian Templates, but I found that it is not very explicit on the involved types. For instance what type does [hamlet|...|]| produce? Without URL-Interpolation, ghci reports t -> Markup but with URL-Interpolation inside, I just get errors.
I am further confused by all the type synonyms involved, e.g. [shamlet|...|] delivers something of type Html, while setMessage expects a Html (). I do not know how to look these up easily: Hoogle often finds nothing on the topic, while Google always finds possibly outdated versions (with examples that no longer work) - sure I get to the newest version eventually, but is there a place where I get an easy overview over these? (Can ghci list all synonyms for a type?)
Note that I actually want to produce the message in a purely functional code fragment, which is later on used by a handler. So that is why I would like to separate the URL rendering from where the hamlet is specified. Thanks for any pointer in the right direction!
I think you want to use getUrlRenderParams. Strangely enough, a related discussion came up on IRC today. Hamlet templates take a URL rendering function as their first argument, and that function must take two parameters: a type-safe URL, and a list of query string parameters. getUrlRender returns a function that doesn't take the query string parameters, which is why you need getUrlRenderParams instead.