SOLVED

Re: Velocity macros being saved.. globally.. or some dark magic like that

Go to solution
Stephen_Baker2
Level 2

Velocity macros being saved.. globally.. or some dark magic like that

I couldn't figure out why my macro was not updating on successive calls when trying to update the code. I did find out what was going on... but why it was... ¯\_(ツ)_/¯

Welp, turns out whenever the script token was saved a version of the macro at that time was "created in memory" - or some such thing like that - using the macro name, and any changes to the macro contents were not actually applying to future calls of the macro. I tried the unplug-it-and-plug-it-in-again method on previews, browser windows, etc., to no avail.

Is this how macros are supposed to function? Is there fine print for macros in Marketo?

Here is an example of two tests I made after updating a macro with new code:

Code 1:

#macro( getCreditUnionNumber3 $list $source )

#foreach ( $creditUnion in $list )

#if ( $creditUnion == $source )

#set ( $phoneNumber = $creditUnion[$source]) )

#break($getCreditUnionNumber)

#end

#set ( $a = $creditUnion )

#set ( $b = $creditUnion[$source] )

union = ${a}<br/>

number = ${b}<br/>

#end

#end

Called by: #getCreditUnionNumber3( $phoneList $leadSource )

Output 1:

number = ${creditUnion[$velocityCount].value}

test union = ${creditUnion[$velocityCount].key}

number = ${creditUnion[$velocityCount].value}

test union = ${creditUnion[$velocityCount].key}

number = ${creditUnion[$velocityCount].value}

test union = ${creditUnion[$velocityCount].key}

(...)

Code 2:

#macro( getCreditUnionNumber $list $source )

#foreach ( $creditUnion in $list )

#if ( $creditUnion == $source )

#set ( $phoneNumber = $creditUnion[$source]) )

#break($getCreditUnionNumber)

#end

#set ( $a = $creditUnion )

#set ( $b = $creditUnion[$source] )

union = ${a}<br/>

number = ${b}<br/>

#end

#end

Called by: #getCreditUnionNumber( $phoneList $leadSource )

Output 2:

number = ${b}

test union = [phone number was here]

number = ${b}

test union = [phone number was here]

number = ${b}

test union = [phone number was here]

(...)

It might be hard to follow along with all the noise above.

But if you track carefully, you'll see that the macro names changed for the two outputs, but the code contents did not change. However, if you are still following along , the rendered output of the loop for Code 1 is using a previous iteration of the macro "#getCreditUnionNumber3" where I was messing around with key-value pairs. (I had to increment the name to get past the issue and am using v3 for the example.) You should see that the current macros in Code 1 and Code 2 do not reference keys or values anywhere.

Btw, the code I was using was busted which was why literal VTL was being printed. That was resolved, don't think it's related.

The solution I found was renaming the macro every time I made a change to the macro contents.

1 ACCEPTED SOLUTION

Accepted Solutions
SanfordWhiteman
Level 10 - Community Moderator

Re: Velocity macros being saved.. globally.. or some dark magic like that

Yes, Velocimacros are cached by the engine (this is the norm in production Velocity installs). Indeed, versioning the name is the way to go.

I have a couple more things to add on this... back later.

View solution in original post

8 REPLIES 8
SanfordWhiteman
Level 10 - Community Moderator

Re: Velocity macros being saved.. globally.. or some dark magic like that

Yes, Velocimacros are cached by the engine (this is the norm in production Velocity installs). Indeed, versioning the name is the way to go.

I have a couple more things to add on this... back later.

SanfordWhiteman
Level 10 - Community Moderator

Re: Velocity macros being saved.. globally.. or some dark magic like that

OK, a few more thoughts on Velocimacros.  I've got a short blog post coming out about them, but I'm not worried about redundancy since only you and Mark are probably reading this thread.

As I said, VMs are cached until the Velocity engine context and/or whole JVM restarts (for practical purposes in Marketo, these are both "forever," I just want to be precise).  So your experience is expected, even if not documented by Marketo themselves it is in the Velocity docs (OK, it could be clearer even in the docs, but it gets at least a passing mention). You have to change the name of the macro, you can't ever "recompile" it. For this reason I start out by appending _v1 to any #macro name.

On the wider level, you should note that unless you're storing a ton of code in a Velocimacro (think 500+ LOC), the macro actually executes more slowly than the exact same code used inline.

Now, when I say "more slowly" I mean you'd only notice it over the course of 100,000+ executions, but you do take a ~10-20% hit. This surprised me at first because you might think with the code being precompiled to Velocity's version of bytecode and then cached in that form, it couldn't help but be faster, or at least the same. But it turns out the additional function call overhead more than counterbalances the caching efficiency. Go figure.

So the reasons -- and these are extremely valid ones! -- to use macros are only encapsulation* better programming style, DRY principle, etc. If you're only executing the macro once, in only one token, perhaps it doesn't need to be a macro at all. What I'd like to see is the actual source data you're processing here (the $list and $source variables). This code is quite strange looking:

#if( $creditUnion == $source )

#set( $phoneNumber = $creditUnion[$source] )

If $list is an ArrayList and $creditUnion is a Hash (LinkedHashMap) and you're trying to find which object in the list is strictly equal to some reference object ($source) that much makes sense.

But then $source is also a Hash, and $creditUnion[$source] is a circular reference. It's impossible to get a circular reference injected into Velocity by Marketo. So you'd have to be creating it yourself, which is... a terrible idea.

* real encapsulation being nonexistent in VTL due to the global namespace, but close enough

Justin_Norris1
Level 10 - Champion Alumni

Re: Velocity macros being saved.. globally.. or some dark magic like that

Sanford Whiteman wrote:

...but I'm not worried about redundancy since only you and Mark are probably reading this thread.

Never underestimate who's lurking in the shadows Sanford Whiteman​. Sponging up your knowledge is my main professional development activity.

That being said, redundancy doesn't exactly hurt when it comes to velocimacros.

SanfordWhiteman
Level 10 - Community Moderator

Re: Velocity macros being saved.. globally.. or some dark magic like that

Appreciate it, Justin! I mentioned Mark because he Helpful'd it even on a Friday afternoon.

Stephen_Baker2
Level 2

Re: Velocity macros being saved.. globally.. or some dark magic like that

$list is a key/value pair of vendors and their phone number to use. The idea was to create a list that can scale easily as we add more vendors.

{

"vendor1":"phone1",

"vendor2":"phone2",

"vendor3":"phone3",

"vendor4":"phone4",

(...)

}

The example macro provided was a Frankenstein of testing different methods half finished. Final code ended up being this, where $source is the vendor name to look up:

#macro( getCreditUnionPhoneNumber $list $source )

#foreach ( $creditUnion in $list.entrySet() )

#if ( $creditUnion.key == $source )

#set ( $phoneNumber = $creditUnion.value)

#end

#end

#end

This could be hard coded, we were just trying to be cool with macros. It made the code prettier but this is email so it must follow that template code be ugly.

I don't think we'll continue with macros unless we "instantiate" them from a global library-type token for use anywhere they are needed.

SanfordWhiteman
Level 10 - Community Moderator

Re: Velocity macros being saved.. globally.. or some dark magic like that

If you're using a Hash, why are you iterating over it? You can seek the key directly, that's what Hashes are for.

#set( $phoneNumber = $list[$source] )

Stephen_Baker2
Level 2

Re: Velocity macros being saved.. globally.. or some dark magic like that

I must've been doing something syntactically wrong initially because I thought I had tried that method - getting blank results back - but got lost in a rabbit hole of how to declare and use VTL objects.

Mark_Price
Level 7

Re: Velocity macros being saved.. globally.. or some dark magic like that

The Velocity keeps me checking community for updates. 

So when starting with Velocity, I had made a Macro to learn and it just wasn't doing what it 'should' have.  This was a while ago so it could have also been a syntax error.  Going to give it another go with versioning, seems like that would explain my headaches.