We are using Velocity to create email templates. For that, we are adding all the required parameters to a HashMap and that HashMap we are adding to the VelocityContext object. It generally works fine, but sometimes(not always) few variables are not being replaced by velocity. I also checked that these variables did exist in HashMap before being added to the context. Please suggest what might be wrong.
Hard to guess the reason without seeing the code... typos? name collision?
There's a debugging technique (if you don't use the SecureUberspector) which consists in displaying $object.class.name from inside the template.
Related
I am using MethodCall.setsField() to try to set an instance field on another instance.
My generated class that is doing the field-setting, GC, is trying to set the value of an instance field in an instance of something it has created (CI). So the field's declaring type is CI; my field-setting code resides in GC (which is in the same package as CI but otherwise unrelated to it).
The ByteBuddy checks seem to indicate that although GC and CI are in the same package, GC must be assignable to CI in order to set this field! That greatly surprised me, but I am not a bytecode expert, and I might very well be overlooking something obvious. Could someone kindly explain why this check is necessary?
The method call sets the field implicitly on the this instance on which the method is invoked. For this to be possible, a non-static field must be declared by a super type of the type on which the method is invoked.
If you think this is too strict, please file an issue with an example of the code you are trying to generate, including the code to generate it which is currently failing. Maybe I am not thinking straight about this and if there's a restriction to be lifted, I would surely do it.
Where in the VB6/VBA project references do Array(), LBound(), and UBound() come from..? When I'm typing in code, they don't appear in the Autocomplete list (ctrl+space), they don't get autocompleted, and they must be typed out completely before the text editor recognizes them. And only when a left-parenthesis is typed will ToolTipText pop up with the command syntax. Also, they do not appear anywhere in Object Explorer.
There's probably a basic concept in play here that I'm not aware of. And it makes me wonder, what other commands/statements/keywords are hidden in the same way..? Is there a list somewhere..? I googled for info but didn't find anything, probably because I don't know what I'm looking for and using the wrong search terms.
I ask these questions because I have the habit of prefixing many VB6 built-in functions like this: VBA.Left(), VBA.Len, VBA.Instr(), and so on. But I can't figure out what reference prefeix to use with Array(), LBound(), and UBound(), or perhaps they're so basic to VB6 that they don't have one.
I do this prefixing because years ago I was working on a large project, and there were functions I was trying to use with the same name in different reference libraries. I was a newbie and it took me a while to figure out, and it was causing tremendous problems since the functions were just NOT working the way I thought they were supposed to. It was then that I developed the prefixing habit after I figured it out. It's just easier that way, and always ensures the expected functions are being used.
The reason that they don't appear as IntelliSense options (and also why they don't appear in the Object Browser) is that they aren't declared in the VBE7.dll typelib for some reason that's beyond me. The Array function is implemented in the .dll as rtcArray. The utility of knowing that is dubious, in that its sole argument is a ParamArray, which means that if you called it directly from VBE7.dll you would need to create an array to have it feed you back the same array... This partially explains why it isn't on the typelib - a COM call would need to do the same thing, and the marshaling would basically be doing the same thing as what you'd expect the function to return.
LBound and UBound don't even appear as functions in the export table, so my guess is that they are handled more like "keywords" than first class functions internally. This makes some sense, in that it's fairly trivial to check the bounds of a SAFEARRAY if you have a pointer to the automation struct (you just index into the rgsabound array at the end of it and read the cElements and lLbound from it. Again a guess, but I'd assume that this allows for flexibility in letting LBound and UBound function with both fixed length and variable length arrays. In the fixed case, the array is basically managed as a block of memory with an indexer (more like a VT_CARRAY than a VT_SAFEARRAY). I'd imagine that handling this internally was easier or more convenient than providing first-class functions.
You won't find Debug in the Object Browser either, nor its methods Assert and Print.
You won't find Statements that are used like methods, like Open, Close, Get and Put, which is why you don't get any Intellisense when you use those statements, and the syntax must be memorized.
You will find Load and Unload as members of VBA.Global, but it's not clear what they belong to otherwise, and their arguments are late-bound Objects. The VBA documentation states that Load and Unload are Statements, even though the Object Browser shows them as Methods.
Keep in mind that you can move the order of references and it will make a difference. Try moving VBA to the top or near the top of your list of references. I believe that if something else also defines a BASIC keyword, it steals it, in a sense. I once had Right disappear and because I was not aware of the order of references, had to change all references of Right to VBA.Right. It's possibly the same with the ubound, lbound, or array.
VB in VS2008 under Windows 7 (64):
I need to change the value of a Property of a Component at some unpredictable time in DesignMode, and want the previously unknown new value to be embedded in the executable that results from VS compilation (as opposed to serializing it to some external file).
I have resorted to a text edit to swap the new value into the autogenerated Component initialization code in a prebuild event handler. This works fine, but it is a little hacky for my taste. Is there some way instead to force VS to refresh that text?
By luck, I found something that seems to work to force VS to autogenerate initialization code for the runtime instance of a Component, which is what I was after (I needed to have successful communication between designtime and runtime for Components -- easy for Controls, which use the latest designtime BackgroundImage bitmap at runtime (you need only to hide the Property value in the bitmap, which can be done entirely within the rules by using GetPixel and SetPixel). I considered various hacks, but I hit upon the following, which works and makes sense (though I might be completely FoS about the "why". If you know better, please educate me):
As I understand it, soon after a Component is dropped on a design surface in VS (and before it is rendered in the Component Tray), Visual Studio adds it to a collection of Components belonging to a Container. Adding it to the Container's collection is one step in a sequence of happenings that includes Visual Studio's autoregeneration of the Init procedure that will be used for the Component's root at runtime, and which includes values for the Public Properties of the Component. If you overload the Set Site procedure (the creation of ISite is an early step in that sequence) for your Component, and set a value for one of its Public Properties in the Overload, that value will show up in the autoregen text. This is almost what I wanted, except that it only worked when VS called Set Site, and I needed it to happen any time I chose.
Then I took a flyer, and in the UI that sets the Property value in question (at some unknowable time), I added code to remove the Component from the Container's collection and then re-add it, hoping that this might again set off a sequence of happenings that would lead to VS again autoregenerating the Init code, this time with the new value of the Property. It apparently did. Yay.
By deciding when to re-add a Component to the Container's Components collection, I am now able to force VS to write in the autogenerated Init text any value I assign to a Public Property of that Component, and hence embed the value in the executable when it is compiled.
This technique is vulnerable to changes in the (undocumented) way that Microsoft implements autogeneration, and so is arguably a hack. But even documented features are subject to change. Backward-compatibility is a nice idea, but sometimes it has to give way. And delivery is a requirement. It would be great to know that your code will still be good in any future version of VS, but that, sadly, can't happen, hack or no.
Of course, documented features are in general less subject to change than undocumented ones. But the logic of autogeneration after all the initial Property values are set is pretty compelling. That Microsoft uses the same sequence later on is not so inherently logical, but doing it a different way would cost Microsoft money for no apparent gain. And Microsoft and their ilk (are legally required to) make decisions based on the bottom line. So the status quo seems like a good bet.
I'm using Twitter Bootstrap on a project at the moment, including the LESS files and compiling with some additional LESS code that we've written.
The latest release has meant we need to override some of the Bootstrap LESS variables. One option here was to maintain a modified copy of Bootstrap which we patch on each release.
But I note that it's possible to override a variable defined in an #import LESS file by re-declaring the variable after the import statement.
E.g.:
#import "twitter-bootstrap/bootstrap.less";
// Restore base font size to pre 2.1.1 defaults
#baseFontSize: 13px;
// Add some custom LESS code here
Is this bad practice? Is it an artifact of the way the LESS compiler works, or an intended part of it? I couldn't find much information on this, although I did find the following two references:
Because of a bug in the Less compiler, you can override the “constant” value of a variable by changing it after it is initially declared.
http://rubysource.com/how-to-customize-twitter-bootstrap%E2%80%99s-design-in-a-rails-app
and
Customize the columns and gutters by overriding these three variables (after the grid.less import has been declared).
http://semantic.gs/
The LESS site itself says that variables are 'constants':
http://lesscss.org/
Note that variables in LESS are actually ‘constants’ in that they can only be defined once.
But then I see other sites using this approach.. It's certainly easier than maintaining a vendor branch and seems to work fine with less.js.
Would appreciate any thoughts on whether this is a bad thing to do or not!
Ok! One of the above issues led to a discussion of the intended behaviour, and it turns out that overriding LESS variables is fine.
Your declarations will overwrite each-other in the same scope in CSS; The same is true for LESS.
https://github.com/cloudhead/less.js/issues/297
Like in CSS, overriding within a scope is an intended way to use LESS.
It´s ok!
I usually create a less file with "components" and variables with a default value. Then I import after that a file with same variables but "customers" values, overwritting default ones. In that way i have only to change some values to create a new design for each customer.
It´s ok and very useful.
We are in the progress of introducing PostSharp in one of our projects. It's been working great so far! There is one thing though that we haven't managed to solve: how to fire an advice conditionally.
Details:
- we have an attribute StopWatchAttribute which makes it possible to record the time needed to run methods
- this attribute accepts an enumeration "LoggingLevel" which is set in the config file with values like 0, 1, 2 etc
- this parameter is read in a base class called BaseService during runtime: new BaseService().CurrentLoggingSettings
- we tried to set up the attribute constructor like StopWatchAttribute(new BaseService().CurrentLoggingLevel) but we get a compile error: an attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
--> summary: we would like the advice to be called conditionally and the condition depends on the parameter in the constructor of the attribute.
Is this possible to do?
Thanks for your help,
Andras
You cannot give variables to attributes, PostSharp or not. Since you're already reading the values from the config, just set your aspect to do the same on the Initialize() method. Override it in the aspect class and then save the value to a local field. You can use that field throughout the aspect. This compiles the value into the aspect essentially hard coding it.
Or, you can pull the value from the config from your advice method (OnMethodStart, etc) so that you can change it in the config at runtime. This is a more 'flexible' way to do it as it doesn't hard code anything.
Remember, your variables are being set at Runtime. PostSharp is a post-compile framework which means it does it's work long before your variables are even known to JIT.