Elasticsearch scala elastic4s settings from property file - scala

is there a way how to pass settings to elastic4s from property file? The following way works but it is not flexible in munltienvironment:
val settings = ImmutableSettings.settingsBuilder().put("cluster.name","elasticsearch").build()
val client = ElasticClient.remote(settings, "154.86.209.242" -> 9300, "153.89.219.241" -> 9300)
I tried java configuration file elasticsearch.yaml as mantioned in java doc but that doesn't work.
Any suggestion here?

You can do this using the same method you would for the Java client. The ImmutableSettings is a Java Client class not something that is specific to elastic4s.
To load your properties file from the classpath, eg if you have something in src/main/resources/com/package/settings.props
ImmutableSettings.settingsBuilder().loadFromClasspath("/com/package/mysettings.yaml")
Or if you want to load from an input stream:
ImmutableSettings.settingsBuilder().loadFromStream(myinputstream)
There are other methods too, just check out the ImmutableSettings.settingsBuilder object.

Related

How to dynamically load a JAR file with Vert.x JavaScript?

Using Vert.x JavaScript (3.8.4), I want to dynamically load a JAR file at runtime. This is necessary because that file might not exist when my Vert.x application gets started. Ideally, I would like to be able to use code like this:
// load custom JAR file
requireJar("path/to/dynamic.jar");
// use class from dynamically loaded package
var instance = new com.mydynamicpackage.MyCustomClass();
How can I achieve this?
You might find this answer to be helpful:
How to access external JAR files from JavaScript using Rhino and Eclipse?
Another approach that is valid would be to provide the jar with other means, i.e. not via a javascript implementation, to check afterwards, if it is available and then deal with the case if it is not.
java.lang.Class.forName( 'com.mydynamicpackage.MyCustomClass' )
This will throw an error, if MyCustomClass does not exist.
Loading jars at runtime might not be a good idea if you cannot determine they are loaded from a not trustworthy source. This is at least true for the java world.
Based on this answer, I have created the following JavaScript function for dynamically loading a class from a JAR file:
var requireJavaClass=(function(){
var method=java.net.URLClassLoader.class.getDeclaredMethod("addURL",java.net.URL.class);
method.setAccessible(true);
var cache={};
var ClassLoader=java.lang.ClassLoader;
var File=java.io.File;
return function(classname,jarpath){
var c=cache[classname];
if (c) return c;
if (jarpath) {
var cl=ClassLoader.getSystemClassLoader();
method.invoke(cl,new File(jarpath).toURI().toURL());
cl.loadClass(classname);
}
return cache[classname]=Java.type(classname);
}
})();
The equivalent to the snippet I posted in the my question would be:
var MyCustomClass=requireJavaClass("com.mydynamicpackage.MyCustomClass","path/to/dynamic.jar");
var instance = new MyCustomClass();
So far, I have only tested this with Vert.x 3.8.5 running in JRE8, i.e. I can't say if this also works in older Vert.x versions or with JRE9+.

Scala way choosing configuration regarding different environment

My application needs to read configuration file either from the resource directory or from s3.
For local development, I need to read it from the local resource directory. So, when build my project, I don't put the configuration file config.properties into my application jar file. In this case, it should read the configuration from S3. When I can think of doing this scala is pretty much like what I do it by java
val stream : InputStream = getClass.getResourceAsStream("/config.properties")
if (stream != null) {
val lines = scala.io.Source.fromInputStream( stream ).getLines
} else {
/*read it from S3*/
}
But I think scala gives a more functional programing sytax. Any advice?
There are probably better ways to go about what you're after, but here's a more-or-less straight translation of the posted code.
val lines:Iterator[String] = Option(getClass.getResourceAsStream("/config.properties"))
.fold{/*read from S3
return Iterator*/}(io.Source.fromInputStream(_).getLines)

How to set arrays of string to #EnableJpaRepositories from property files

I have a jpa configuration file with #EnableJpaRepositories annotaion. I set this annotaion value from application.properties file like this :
#EnableJpaRepositories("${jpa.repository.packages}")
public class JPAConfiguration {
....
}
and here is my application.properties file:
jpa.repository.packages=com.epms.model
and it works perfect. but i want to specify multiple packages for #EnableJpaRepositories . so i changed my config file to this :
jpa.repository.packages=com.epms.model,com.ecms.model
and also configuration file to this :
#EnableJpaRepositories("#{'${jpa.repository.packages}'.split(',')}")
public class JPAConfiguration {
}
but it's not working . any idea ? how can i do this in my configuration file?
As #amicoderozer is asking, if your classes share a common base package you only must indicate that root package.
If it's not your case (despite you are loading from a config file or you are declaring them manually) maybe the problem (will help posting any Exception or Runtime trace) is the way the split method is used. It returns an array, and I guess the generated code will be like this:
#EnableJpaRepositories("jpa.repository.packages1","jpa.repository.packages2")
That code doesn't compile.
Never tried Spring EL inside the annotation of a component, but despite this, maybe you should indicate the basePackages this way:
#EnableJpaRepositories(basePackages = "#{'${jpa.repository.packages}'.split(',')}")
If doesn't work, I recomend you first test it by manual array declaration:
#EnableJpaRepositories(basePackages = { "com.epms.model","com.ecms.model" })
Be sure all works as you expect, and then try again reading and parsing from config file.
UPDATE:
After some readings, I've concluded that is not possible do what you want. The SpEL is allowed in many places but for annotations there is only documentation and working examples with #Value annotation.

Titan 0.9.0.M2 custom attribute serializer- HashMap as a property value

Titan version: 0.9.0.M2
I'm trying to implement a custom serializer for using a HashMap as a property value. I have written my class according to the instructions provided in here. It implemets AttributeSerializer,has an equals method, and finally a no argument constructor.
I have set my configuration options as follows:
attributes.custom.attribute10.attribute-class = java.util.HashMap
attributes.custom.attribute10.serializer-class = com.graph.HashMapSerializer
I have packaged the serializer into a jar and placed in the lib folder of the Titan distribution. I have tried to start Titan but see the error 'Need to set configuration value: root.attributes.custom.serializer-class' and also 'Could not instantiate configured serializer class' in the 'gremlin-server' logs. I have tried a bunch of options including changing the attribute number and placing in the jar in couple of different places but with no success.
Please kindly comment on whether I am doing this the right way and also possible solutions please. I have read in a Titan related post that some configuration keys might change from version to version, can this be the reason somehow?
Also can anyone please comment on how to specify the full 'custom-class' name , 'custom-serializer' name and where exactly to place the jar?
Thanks for your time.
Placing the jar under $TITAN_HOME/lib is fine, but I think your properties should look like this:
attributes.custom.attribute1.attribute-class = java.util.HashMap
attributes.custom.attribute1.serializer-class = com.graph.HashMapSerializer
The example in the documentation mentions that they already had 9 custom attributes configured, so that's why it was using attribute10. You can verify which serializers are set in your graph using the TitanManagement interface.
$ ./bin/gremlin.sh
\,,,/
(o o)
-----oOOo-(3)-oOOo-----
plugin activated: tinkerpop.server
plugin activated: tinkerpop.utilities
plugin activated: tinkerpop.hadoop
plugin activated: tinkerpop.tinkergraph
plugin activated: aurelius.titan
gremlin> graph = TitanFactory.build().set('storage.backend','berkeleyje').set('storage.directory','/home/vagrant/titan-0.9.0-SNAPSHOT-hadoop1/db/berkeley').open()
==>standardtitangraph[berkeleyje:/home/vagrant/titan-0.9.0-SNAPSHOT-hadoop1/db/berkeley]
gremlin> mgmt = graph.openManagement()
==>com.thinkaurelius.titan.graphdb.database.management.ManagementSystem#78226c36
gremlin> mgmt.get('attributes.custom.attribute10.attribute-class')
==>null
gremlin> mgmt.get('attributes.custom.attribute1.attribute-class')
==>java.util.HashMap

Read property file under classpath using scala

I am trying to read a property file from classpath using scala. But it looks like it won't work, it is different from java. The following 2 code snippet, one is java (working), another is scala (not working). I don't understand what is the difference.
// working
BufferedReader reader = new BufferedReader(new InputStreamReader(
Test.class.getResourceAsStream("conf/fp.properties")));
// not working
val reader = new BufferedReader(new InputStreamReader(
getClass.getResourceAsStream("conf/fp.properties")));
Exception in thread "main" java.lang.NullPointerException
at java.io.Reader.<init>(Reader.java:78)
at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf$.main(FPConf.scala:31)
at com.ebay.searchscience.searchmetrics.fp.conf.FPConf.main(FPConf.scala)
This code finally worked for me:
import java.util.Properties
import scala.io.Source
// ... somewhere inside module.
var properties : Properties = null
val url = getClass.getResource("/my.properties")
if (url != null) {
val source = Source.fromURL(url)
properties = new Properties()
properties.load(source.bufferedReader())
}
And now you have plain old java.util.Properties to handle what my legacy code actually needed to receive.
I am guessing that your BufferedReader is a java.io.BufferedReader
In that case you could simply do the following:
import scala.io.Source.fromUrl
val reader = fromURL(getClass.getResource("conf/fp.properties")).bufferedReader()
However, this leaves the question open as to what you are planning to do with the reader afterwards. scala.io.Source already has some useful methods that might make lots of your code superfluous .. see ScalaDoc
My prefered solution is with com.typesafe.scala-logging. I did put an application.conf file in main\resources folder, with content like:
services {
mongo-db {
retrieve = """http://xxxxxxxxxxxx""",
base = """http://xxxxxx"""
}
}
and the to use it in a class, first load the config factory from typesafe and then just use it.
val conf = com.typesafe.config.ConfigFactory.load()
conf.getString("services.mongo-db.base"))
Hope it helps!
Ps. I bet that every file on resources with .conf as extension will be read.
For reading a Properties file i'd recommend to use java.util.ResourceBundle.getBundle("conf/fp"), it makes life a little easier.
The NullPointerException you are seeing is caused by a bug in the underlying Java code. It could be caused by a mistyped file name.
Sometimes you get this error also if you're trying to load the resource with the wrong classloader.
Check the resource url carefully against your classpath.
Try Source.fromInputStream(getClass.getResourceAsStream(...))
Try Source.fromInputStream(getClass.getClassLoader.getResourceAsStream())
Maybe you are using other classloaders you can try?
The same story goes for Source.fromUrl(...)
If you're trying to load configuration files and you control their format, you should have a look at Typesafe's Config utility.
The Null Pointer Exception you are getting is from getResourceAsStream returning null. The following junit.scala snippet shows how there is a difference in class vs classloader. see What is the difference between Class.getResource() and ClassLoader.getResource()?. Here I assume fileName is the name of a file residing in the class path, but not a file next to the class running the test.
assertTrue(getClass.getClassLoader().getResourceAsStream(fileName) != null)
assertTrue(getClass.getClassLoader().getResourceAsStream("/" + fileName) == null)
assertTrue(getClass.getResourceAsStream(fileName) == null)
assertTrue(getClass.getResourceAsStream("/" + fileName) != null)