Scala dynamic String interpolation - Read from properties file - string

I tried to get the log message from message.properties and did string interpolation with that log message.In this time,The log message is not interpolated with original message.
I am not able to get string interpolated result and am getting the output as log message what i have specified in properties file
Here I dont want to hard code any log message in scala file,Instead of this,I want to get all message from properties file and redirected into application log after interpolating string value.
import com.typesafe.config.ConfigFactory
import grizzled.slf4j.Logging
object Test extends Logging {
def main(args: Array[String]){
val subjectArea="Member"
val messageProp = ConfigFactory.load("message.properties")
val log=messageProp.getString("log.subject.area")
debug(s"$log")
}
}
message.properties
log.subject.area=The Subject Area : $subjectArea
Console Output: The Subject Area : $subjectArea
i want this output : The Subject Area : Member
Thanks in advance!!!
Test.scala
message.propeties

This is not a string interpolation problem. You want a lightweight templating engine (e.g. http://jtwig.org/documentation/quick-start/application or something else). I feel that most of them would be an overkill if your problem is as simple as in the snippet you've provided.
If you want to do something more or less complex, then sure, go with template engines.
Otherwise, I'd just go with string substitution.

String interpolation only works with constants. To do what you want dynamically, you need to write some explicit processing yoruself (or use a template engine library). Something like this, perhaps?
val substPattern = """\$\{(.+?)\}""".r
import java.util.regex.Matcher.{ quoteReplacement => qq }
def processSubstitutions(
input: String,
vars: Map[String, String]
) = substPattern.replaceAllIn(
input, { m =>
val ref = m.group(1)
qq(vars.getOrElse(ref, ref)
}
)
val vars = Map("subjectArea" -> "Member")
val messageProp = ConfigFactory.load("message.properties")
val log=processSubstitutions(
messageProp.getString("log.subject.area"),
vars
)

Related

how to correlate using groovy code in jmeter?

1) In my response body comes like json format.
2) Some expected reason ,i have changed that body json to normal text using below code and working expected way
import groovy.json.*
String js = vars.get("cAccountDetails")
def data = new JsonSlurper().parseText(js)
log.info("the value is "+ data)
vars.putObject('data', data)
3) This code meaning converted json to normal text and stored in some variable thats "data"
4) so my response stored in "data" variable .
5) From "data", how can i extract **specific data** using groovy code or some other code?
import java.util.regex.*
import java.util.regex.Matcher
import java.util.regex.Pattern
def matches = (data =~ '{accountDetails=\\[(.*)\\],')
vars.putObject('matches', matches)
The above code using for correlation purpose {"matches" VARIABLE will store extracted value}
but above code is not working ,how can i fix this issue ?
Thanks in advance!!
We cannot help you unless you share your cAccountDetails variable value and indicate what do you need to extract from it.
From the first glance you regular expression should look a little bit different, i.e.
def matches = (data =~ /accountDetails=[(.*)],/)
More information:
Apache Groovy - Find Operator
Apache Groovy - Why and How You Should Use It

F Strings and Interpolation using a properties file

I have a simple python app and i'm trying to combine bunch of output messages to standardize output to the user. I've created a properties file for this, and it looks similar to the following:
[migration_prepare]
console=The migration prepare phase failed in {stage_name} with error {error}!
email=The migration prepare phase failed while in {stage_name}. Contact support!
slack=The **_prepare_** phase of the migration failed
I created a method to handle fetching messages from a Properties file... similar to:
def get_msg(category, message_key, prop_file_location="messages.properties"):
""" Get a string from a properties file that is utilized similar to a dictionary and be used in subsequent
messaging between console, slack and email communications"""
message = None
config = ConfigParser()
try:
dataset = config.read(prop_file_location)
if len(dataset) == 0:
raise ValueError("failed to find property file")
message = config.get(category, message_key).replace('\\n', '\n') # if contains newline characters i.e. \n
except NoOptionError as no:
print(
f"Bad option for value {message_key}")
print(f"{no}")
except NoSectionError as ns:
print(
f"There is no section in the properties file {prop_file_location} that contains category {category}!")
print(f"{ns}")
return f"{message}"
The method returns the F string fine, to the calling class. My question is, in the calling class if the string in my properties file contains text {some_value} that is intended to be interpolated by the compiler in the calling class using an F String with curly brackets, why does it return a string literal? The output is literal text, not the interpolated value I expect:
What I get The migration prepare phase failed while in {stage_name} stage. Contact support!
What I would like The migration prepare phase failed while in Reconciliation stage. Contact support!
I would like the output from the method to return the interpolated value. Has anyone done anything like this?
I am not sure where you define your stage_name but in order to interpolate in config file you need to use ${stage_name}
Interpolation in f-strings and configParser files are not the same.
Update: added 2 usage examples:
# ${} option using ExtendedInterpolation
from configparser import ConfigParser, ExtendedInterpolation
parser = ConfigParser(interpolation=ExtendedInterpolation())
parser.read_string('[example]\n'
'x=1\n'
'y=${x}')
print(parser['example']['y']) # y = '1'
# another option - %()s
from configparser import ConfigParser, ExtendedInterpolation
parser = ConfigParser()
parser.read_string('[example]\n'
'x=1\n'
'y=%(x)s')
print(parser['example']['y']) # y = '1'

Execute Groovy Script to transform date in Nifi

I'm trying to transform my JSON dates using Nifi. They are imported in this format:
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
def ff = session.get()
if(!ff)return
ff = session.write(ff, {rawIn, rawOut->
// transform streams into reader and writer
rawIn.withReader("UTF-8"){reader->
rawOut.withWriter("UTF-8"){writer->
//parse reader into Map
def json = new JsonSlurper().parse(reader)
// set my variable and define what format it is in
json.date = new Date(json.date as Long).format('HH:mm yyyy-MM-dd')
// Reformat it
json.date = DateFormat.parse("yyyy-MM-dd HH:mm", json.date)
//write changed object to writer
new JsonBuilder(json).writeTo(writer)
}
}
} as StreamCallback)
session.transfer(ff, REL_SUCCESS)
The incoming flowfile has this body:
[{"date":"09:00 2019-05-29","data":460.0,"name":"login"},{"date":"10:00 2019-05-29","data":548.0,"name":"login"},{"date":"11:00 2019-05-14","data":0.0,"name":"login"},{"date":"00:00 2019-06-15","data":0.0,"name":"login"}]
I want this output:
[{"date":"2019-05-29 09:00","data":460.0,"name":"login"},{"date":"2019-05-29 10:00","data":548.0,"name":"login"},{"date":"2019-05-14 11:00","data":0.0,"name":"login"},{"date":"2019-06-15 00:00","data":0.0,"name":"login"}]
The error I get is this:
Can anyone please help me understand where I am going wrong?
The input is a list of the objects in question. The incoming date is a
String -- not a Long.
So the first error is to use json.date as it implies json*.date
(which gives a list of all date).
Next casting the date to Long, create a new Date and then format it is
the wrong way around.
So to change the format of all the date something like this is needed:
json.each{
it.date = Date.parse('HH:mm yyyy-MM-dd', it.date).format('yyyy-MM-dd HH:mm')
}

Binding Groovy TemplateEngine with any variable names

I am trying to write a method that:
Loads a template file (*.tpl) from the local file system
Parameterizes that template file with a list of supplied variables
Best attempt thus far:
String loadParameterizedTemplateByName(String templateName,
String... variables) {
InputStream inputStream =
this.class.classLoader.getResourceAsStream(templateName)
StringWriter writer = new StringWriter()
IOUtils.copy(inputStream, writer, 'UTF-8')
String templateBody = writer.toString()
def binding = variablesAsBinding(variables) // ?!?!
engine.createTemplate(templateBody).make(binding).toString()
}
So for instance say I have the following HelloEmail.tpl template file:
HelloEmail.tpl
==============
Hello ${firstName},
You are awesome! ${someGuy} even says so!
Sincerely,
${me}
Then my desired invocation of this would be:
String firstName = 'John'
String someGuy = 'Mark'
String me = '#smeeb'
String parameterizedTemplate =
loadParameterizedTemplateByName('HelloEmail.tpl', firstName, someGuy, me)
So that the final result is that parameterizedTemplate string has a value of:
println parameterizedTemplate
// Prints:
Hello John,
You are awesome! Mark even says so!
Sincerely,
#smeeb
The trick here is that the method needs to be able to use any list of supplied variables against any supplied template file!
Is this possible to accomplish via reflection? Meaning the TemplateEngine just looks as the supplied list of String variables, and substitutes them for variables of the same name (as found in the template)?
You can pass a Map like so:
import groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
String loadParameterizedTemplateByName(Map variables, String templateName) {
def engine = new groovy.text.SimpleTemplateEngine()
this.class.getResource(templateName).withReader { reader ->
engine.createTemplate(reader).make(variables)
}
}
def result = loadParameterizedTemplateByName('/mail.tpl', firstName:'Tim', someGuy:'StackOverflow', me:'smeeb')
assert result == 'Hello Tim,\n\nYou are awesome! StackOverflow even says so!\n\nSincerely,\nsmeeb'

What function is meant to format/substitute {0} {1} parameters in an string in Grails/Groovy?

I'm just getting started with Groovy/Grails
I noticed the error messages you get when you validate a form look like this:
Property [{0}] of class [{1}] cannot be blank
For example this code to dump the errors to the console
s.errors.allErrors.each
{
println it.defaultMessage
}
Now, it.arguments contains the arguments that need to be filled in here.
The problem is, I can't find any method in the Grails or Groovy documentation that formats strings based on positional parameters like {0}, {1} and substitutes values from an array
I need something like python's %
What is the proper way to format these error strings so the parameters get substituted properly?
These markers are actually replaced using the standard java.text.MessageFormat APIs. If you display the messages using Grail's g:message tag, it will fill in the gaps if you pass a suitable args="..." attribute:
<g:message code="mymessagecode" args="${['size', 'org.example.Something']}"/>
Under certain circumstances (within GSP pages and from controllers IIRC) you cann call the tag like a function:
g.message(code:'mymessagecode',args: ['size', 'org.example.Something'])
Note, that the value to supply as message code is only a symbolic string constant. The actual translation (the message text with the "gaps" in it) will be read by the framework using Spring's reloadable resource bundles.
If all you actually have is a translation text, you can call the message formatting APIs directly. See for example:
import java.text.MessageFormat
...
args = ["english"].toArray()
println(MessageFormat.format("Translation into {0}", args))
// Or - as the method is variadic:
println(MessageFormat.format("Translation into {0}", "english"))
Look what Groovy can do for you, using a little bit of meta-programming.
MessagesBundle_en_US.properties:
greetings = Hello {0}.
inquiry = {0}: How are you {1}?
farewell = Goodbye.
ResourceBundleWithSugar.groovy:
import java.text.MessageFormat
class ResourceBundleUtils {
def propertyMissing(String name) { this.getString(name) }
def methodMissing(String name, args) {
MessageFormat.format(this.getString(name), args)
}
}
ResourceBundle.metaClass.mixin ResourceBundleUtils
def msg = ResourceBundle.getBundle("MessagesBundle", new Locale("en","US"));
println msg.greetings("Serge")
println msg.inquiry("Serge","Mary")
println msg.farewell // You can use also: msg.['farewell'] msg."farewell" or msg.getString("farewell")
Output:
Hello Serge.
Serge: How are you Mary?
Goodbye.

Resources