[
https://issues.apache.org/jira/browse/VELOCITY-986?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Patrick Barry updated VELOCITY-986:
-----------------------------------
Description:
We recently tried to upgrade to 2.4 and 2.4.1 and both had this issue, so we
had to rollback. We have a template looking like this:
[https://my.example.com?size=$|https://my.example.com/?size=$]{input.size}
In our VelocityContext, we have have an InnerContext values that should be used.
IE
{"size"= "1089", "name"="tyler", "age"="28"}
In versions 2.3 and below, this would evaluate to
[https://my.example.com?size=1089|https://my.example.com/?size=1089]
With newest versions, it gives us the number of items in our map. So
[https://my.example.com?size=3|https://my.example.com/?size=1089]
Here is a unit test of our usage. This test includes the ability to register
many different "providers", however, I kept it simple and just used one.
Providers have a prefix, so in the example above, we use a prefix provider of
"input". This allows to "scope" contexts.
{code:java}
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.junit.Test;
import java.io.StringWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class VelocityRegressionTest {
@Test
public void testVelocityTemplate() throws Exception {
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
VariableProviderCaseInsensitiveMap<String> innerMap = new
VariableProviderCaseInsensitiveMap<>("input");
innerMap.put("size", "1098");
innerMap.put("name", "Tyler");
innerMap.put("try", "1");
Context innerContext = new
VariableProviderVelocityContext(List.of(innerMap));
VelocityContext context = new VelocityContext(innerContext);
StringWriter sw = new StringWriter();
String vt = "https://my.example.com?size=${input.size}";
Velocity.evaluate(context, sw, "", vt);
assertEquals("https://my.example.com?size=1098", sw.toString());
}
static class VariableProviderCaseInsensitiveMap<T> extends
CaseInsensitiveMap<String, T> {
private String providerContextPrefix = null;
public VariableProviderCaseInsensitiveMap(final String
providerContextPrefix) {
if (!StringUtils.isBlank(providerContextPrefix)) {
this.providerContextPrefix = providerContextPrefix;
}
}
public String getProviderContextPrefix() {
return providerContextPrefix;
}
public Set<String> getKeys() {
return super.keySet();
}
public Map<String, T> getMap() {return this;}
}
static class VariableProviderVelocityContext extends VelocityContext {
protected final List<VariableProviderCaseInsensitiveMap> providers;
public VariableProviderVelocityContext(
final List<VariableProviderCaseInsensitiveMap> providers
) {
super();
this.providers = providers;
}
private Object lookup(String key) {
for (VariableProviderCaseInsensitiveMap provider : providers) {
final String contextPrefix =
provider.getProviderContextPrefix();
if (contextPrefix.equalsIgnoreCase(key)) {
return provider.getMap();
}
}
return null;
}
@Override
public Object internalGet(String var1) {
return lookup(var1);
}
@Override
public Object internalPut(String key, Object value) {
throw new NotImplementedException("internalRemove is not valid and
is not implemented");
}
@Override
public String[] internalGetKeys() {
List<String> keys = new LinkedList<>();
for (VariableProviderCaseInsensitiveMap provider : providers) {
String prefix = provider.getProviderContextPrefix();
if (StringUtils.isNotBlank(prefix)) {
keys.add(prefix);
} //the prefix is the key name for a context provider.
else {
keys.addAll(provider.getKeys());
}
}
return keys.toArray(new String[0]);
}
@Override
public boolean internalContainsKey(String var1) {
return lookup(var1) != null;
}
@Override
public Object internalRemove(String var1) {
throw new NotImplementedException("internalRemove is not valid and
is not implemented");
}
}
} {code}
was:
We recently tried to upgrade to 2.4 and 2.4.1 and both had this issue, so we
had to rollback. We have a template looking like this:
https://my.example.com?size=${input.size}
In our VelocityContext, we have have an InnerContext values that should be used.
IE
{"size"= "1089", "name="tyler", age="28"}
In versions 2.3 and below, this would evaluate to
[https://my.example.com?size=1089|https://my.example.com/?size=1089]
With newest versions, it gives us the number of items in our map. So
[https://my.example.com?size=3|https://my.example.com/?size=1089]
Here is a unit test of our usage. This test includes the ability to register
many different "providers", however, I kept it simple and just used one.
Providers have a prefix, so in the example above, we use a prefix provider of
"input". This allows to "scope" contexts.
{code:java}
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.junit.Test;
import java.io.StringWriter;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class VelocityRegressionTest {
@Test
public void testVelocityTemplate() throws Exception {
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
VariableProviderCaseInsensitiveMap<String> innerMap = new
VariableProviderCaseInsensitiveMap<>("input");
innerMap.put("size", "1098");
innerMap.put("name", "Tyler");
innerMap.put("try", "1");
Context innerContext = new
VariableProviderVelocityContext(List.of(innerMap));
VelocityContext context = new VelocityContext(innerContext);
StringWriter sw = new StringWriter();
String vt = "https://my.example.com?size=${input.size}";
Velocity.evaluate(context, sw, "", vt);
assertEquals("https://my.example.com?size=1098", sw.toString());
}
static class VariableProviderCaseInsensitiveMap<T> extends
CaseInsensitiveMap<String, T> {
private String providerContextPrefix = null;
public VariableProviderCaseInsensitiveMap(final String
providerContextPrefix) {
if (!StringUtils.isBlank(providerContextPrefix)) {
this.providerContextPrefix = providerContextPrefix;
}
}
public String getProviderContextPrefix() {
return providerContextPrefix;
}
public Set<String> getKeys() {
return super.keySet();
}
public Map<String, T> getMap() {return this;}
}
static class VariableProviderVelocityContext extends VelocityContext {
protected final List<VariableProviderCaseInsensitiveMap> providers;
public VariableProviderVelocityContext(
final List<VariableProviderCaseInsensitiveMap> providers
) {
super();
this.providers = providers;
}
private Object lookup(String key) {
for (VariableProviderCaseInsensitiveMap provider : providers) {
final String contextPrefix =
provider.getProviderContextPrefix();
if (contextPrefix.equalsIgnoreCase(key)) {
return provider.getMap();
}
}
return null;
}
@Override
public Object internalGet(String var1) {
return lookup(var1);
}
@Override
public Object internalPut(String key, Object value) {
throw new NotImplementedException("internalRemove is not valid and
is not implemented");
}
@Override
public String[] internalGetKeys() {
List<String> keys = new LinkedList<>();
for (VariableProviderCaseInsensitiveMap provider : providers) {
String prefix = provider.getProviderContextPrefix();
if (StringUtils.isNotBlank(prefix)) {
keys.add(prefix);
} //the prefix is the key name for a context provider.
else {
keys.addAll(provider.getKeys());
}
}
return keys.toArray(new String[0]);
}
@Override
public boolean internalContainsKey(String var1) {
return lookup(var1) != null;
}
@Override
public Object internalRemove(String var1) {
throw new NotImplementedException("internalRemove is not valid and
is not implemented");
}
}
} {code}
> Regression test failure
> -----------------------
>
> Key: VELOCITY-986
> URL: https://issues.apache.org/jira/browse/VELOCITY-986
> Project: Velocity
> Issue Type: Bug
> Components: Engine
> Affects Versions: 2.4, 2.4.1
> Reporter: Patrick Barry
> Priority: Major
>
> We recently tried to upgrade to 2.4 and 2.4.1 and both had this issue, so we
> had to rollback. We have a template looking like this:
> [https://my.example.com?size=$|https://my.example.com/?size=$]{input.size}
>
> In our VelocityContext, we have have an InnerContext values that should be
> used.
> IE
> {"size"= "1089", "name"="tyler", "age"="28"}
>
> In versions 2.3 and below, this would evaluate to
> [https://my.example.com?size=1089|https://my.example.com/?size=1089]
> With newest versions, it gives us the number of items in our map. So
> [https://my.example.com?size=3|https://my.example.com/?size=1089]
>
> Here is a unit test of our usage. This test includes the ability to register
> many different "providers", however, I kept it simple and just used one.
> Providers have a prefix, so in the example above, we use a prefix provider of
> "input". This allows to "scope" contexts.
>
> {code:java}
> import org.apache.commons.collections4.map.CaseInsensitiveMap;
> import org.apache.commons.lang3.NotImplementedException;
> import org.apache.commons.lang3.StringUtils;
> import org.apache.velocity.VelocityContext;
> import org.apache.velocity.app.Velocity;
> import org.apache.velocity.app.VelocityEngine;
> import org.apache.velocity.context.Context;
> import org.junit.Test;
> import java.io.StringWriter;
> import java.util.LinkedList;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
> import static org.junit.jupiter.api.Assertions.assertEquals;
> public class VelocityRegressionTest {
> @Test
> public void testVelocityTemplate() throws Exception {
> VelocityEngine velocityEngine = new VelocityEngine();
> velocityEngine.init();
> VariableProviderCaseInsensitiveMap<String> innerMap = new
> VariableProviderCaseInsensitiveMap<>("input");
> innerMap.put("size", "1098");
> innerMap.put("name", "Tyler");
> innerMap.put("try", "1");
> Context innerContext = new
> VariableProviderVelocityContext(List.of(innerMap));
> VelocityContext context = new VelocityContext(innerContext);
> StringWriter sw = new StringWriter();
> String vt = "https://my.example.com?size=${input.size}";
> Velocity.evaluate(context, sw, "", vt);
> assertEquals("https://my.example.com?size=1098", sw.toString());
> }
> static class VariableProviderCaseInsensitiveMap<T> extends
> CaseInsensitiveMap<String, T> {
> private String providerContextPrefix = null;
> public VariableProviderCaseInsensitiveMap(final String
> providerContextPrefix) {
> if (!StringUtils.isBlank(providerContextPrefix)) {
> this.providerContextPrefix = providerContextPrefix;
> }
> }
> public String getProviderContextPrefix() {
> return providerContextPrefix;
> }
> public Set<String> getKeys() {
> return super.keySet();
> }
> public Map<String, T> getMap() {return this;}
> }
> static class VariableProviderVelocityContext extends VelocityContext {
> protected final List<VariableProviderCaseInsensitiveMap> providers;
> public VariableProviderVelocityContext(
> final List<VariableProviderCaseInsensitiveMap> providers
> ) {
> super();
> this.providers = providers;
> }
> private Object lookup(String key) {
> for (VariableProviderCaseInsensitiveMap provider : providers) {
> final String contextPrefix =
> provider.getProviderContextPrefix();
> if (contextPrefix.equalsIgnoreCase(key)) {
> return provider.getMap();
> }
> }
> return null;
> }
> @Override
> public Object internalGet(String var1) {
> return lookup(var1);
> }
> @Override
> public Object internalPut(String key, Object value) {
> throw new NotImplementedException("internalRemove is not valid
> and is not implemented");
> }
> @Override
> public String[] internalGetKeys() {
> List<String> keys = new LinkedList<>();
> for (VariableProviderCaseInsensitiveMap provider : providers) {
> String prefix = provider.getProviderContextPrefix();
> if (StringUtils.isNotBlank(prefix)) {
> keys.add(prefix);
> } //the prefix is the key name for a context provider.
> else {
> keys.addAll(provider.getKeys());
> }
> }
> return keys.toArray(new String[0]);
> }
> @Override
> public boolean internalContainsKey(String var1) {
> return lookup(var1) != null;
> }
> @Override
> public Object internalRemove(String var1) {
> throw new NotImplementedException("internalRemove is not valid
> and is not implemented");
> }
> }
> } {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]