Elasticsearch 1.3. - Call custom REST endpoint from Java - java

I am currently building an elasticsearch plugin which exposes a REST endpoint ( starting from this post )
I can call my endpoint with curl like this :
curl -X POST 'http://my-es:9200/lt-dev_terminology_v1/english/_terminology?pretty=-d '{
"segment": "database",
"analyzer": "en_analyzer"
}
My question is how can I call the same endpoint from java, using a transport client ? Could you point me to some tutorial ?

I suggest that you take a look here. It should be a good starting point for you.
Let me sum up :
Considering the following parameters :
String clustername = "...";
String clientTransportHost = "...";
Integer clientTransportPort= "...";
String clientIndex = "...";
String indexType = "...";
Of course you replace the dots with the settings you wish to use.
Then you define your cluster Settings:
Settings settings = ImmutableSettings.settingsBuilder()
.put("cluster.name", clustername).build();
You instantiate the TransportClient object :
TransportClient client = new TransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(clientTransportHost, clientTransportPort));
You can verify your connection using this method :
private void verifyConnection(TransportClient client) {
ImmutableList<DiscoveryNode> nodes = client.connectedNodes();
if (nodes.isEmpty()) {
throw new ElasticsearchException(
"No nodes available. Verify ES is running!");
} else {
log.info("connected to nodes: " + nodes.toString());
}
}
PS: to use the log.info() method you have to instantiate a Logger.
So now you can use the verification method :
verifyConnection(client);
and once you've done all that you can now per example prepare a search :
SearchResponse response = client.prepareSearch(clientIndex)
.setTypes(indexType)
.addFields("...", "...")
.setSearchType(SearchType.DEFAULT)
.execute()
.actionGet();
PS : Tested on Elasticsearch 1.3

Related

AWS SSM parameter store not fetching all key/values

Could someone let me know why the below code only fetching few entries from the parameter store ?
GetParametersByPathRequest getParametersByPathRequest = new GetParametersByPathRequest();
getParametersByPathRequest.withPath("/").setRecursive(true);
getParametersByPathRequest.setWithDecryption(true);
GetParametersByPathResult result = client.getParametersByPath(getParametersByPathRequest);
result.getParameters().forEach(parameter -> {
System.out.println(parameter.getName() + " - > " + parameter.getValue());
});
GetParametersByPath is a paged operation. After each call you must retrieve NextToken from the result object, and if it's not null and not empty you must make another call with it added to the request.
Here's an example using DescribeParameters, which has the same behavior:
DescribeParametersRequest request = new DescribeParametersRequest();
DescribeParametersResult response;
do
{
response = client.describeParameters(request);
for (ParameterMetadata param : response.getParameters())
{
// do something with metadata
}
request.setNextToken(response.getNextToken());
}
while ((response.getNextToken() != null) && ! respose.getNextToken.isEmpty());
Here is the code, based on the code above, for the new 2.0 version of AWS SSM manager. Notice I have set the maxResults to 1 to prove out the loop. You will want to remove that. AWS has mentioned that in the new code they wanted to emphasize immutability.
Using this dependency:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>ssm</artifactId>
<version>2.10.32</version>
</dependency>
I came up with this code:
private void refreshCache() {
StopWatch sw = StopWatch.createStarted();
GetParametersByPathRequest request = GetParametersByPathRequest.builder()
.path(prefix)
.withDecryption(useDecryption)
.maxResults(1)
.build();
GetParametersByPathResponse response;
do {
response = ssm.getParametersByPath(request);
for (Parameter p : response.parameters()) {
//do something with the values.
}
request = GetParametersByPathRequest.builder()
.path(prefix)
.withDecryption(useDecryption)
.nextToken(response.nextToken())
.maxResults(1)
.build();
}
while (StringUtils.isNotBlank(response.nextToken()));
LOG.trace("Refreshed parameters in {}ms", sw.getTime());
}
private void getSsmParams() {
AWSSimpleSystemsManagement client = AWSSimpleSystemsManagementClientBuilder.defaultClient();
GetParametersByPathRequest request = new GetParametersByPathRequest();
request.withRecursive(true);
request.withPath('/your/path/parameterName').setWithDecryption(true);
GetParametersByPathResult response;
do {
response = client.getParametersByPath(request);
for (Parameter p : response.parameters()) {
//do something with the values. maybe add to a list
}
request.setNextToken(response.getNextToken())
}
while (StringUtils.isNotBlank(response.getNextToken()));
}
Above piece of code worked for me .ssm only sends 10 parameters at a time, so if you want to fetch more than 10 parameters from ssm parameter store programatically you will have to use multiple calls to fetch them. here the token is important , if there are more values in the path (request.withPath('/your/path/parameterName')) you have given, it will send a token indicating that there are more values in the given path ,and you will have to make the following request with the token received from the previous request in order to get the rest of the values.

Rest Api Zabbix (method : item.get) how to get full names of the metrics

My method for obtaining id metrics from zabbix:
protected String getItemId(String host, String zabbixHostItemName) {
JSONObject hostItemsFilter = new JSONObject();
hostItemsFilter.put("name", new String[]{zabbixHostItemName});
return connectZabbix.zabbixAPI.call(RequestBuilder.newBuilder()
.method("item.get")
.paramEntry("filter", hostItemsFilter)
.paramEntry("host", host)
.build()).getJSONArray("result").getJSONObject(0).getString("itemid");
}
What the following request body generates:
{
"jsonrpc": "2.0",
"method": "item.get",
"params": {
"filter": {
"name": [
"myItem"
]
},
"host": "myHost"
}
}
It almost always works well.
The problem occurs when Zabbiks returns parameterized metric names.
For example, if you request a metric:
Incomming network traffic on lan900
My method returns an error, because the data on the network interfaces parameterized.
If I request all the metrics on the host from the zabbix then for example the necessary "Incomming network traffic on" will match the name:
Incomming network traffic on $1
How to build a query that would find the itemid from the full name of the metric and host?
The current item API cannot expand macros automatically, it's a feature implementend for instance in the trigger API (expandComment, expandDescription, expandExpression).
You can upvote this feature request.
You can do a first query for "Incoming network traffic on $1", which will return an array of matching items, one for each network interface in your case.
Then you can filter on the 'key_' field with the real interface name.
A small python sample:
f = { 'name' : 'Incoming packet on $1' }
hostname = 'somehostname'
itemObj = zapi.item.get(filter=f, host=hostname, output=['itemids', 'name', 'key_'] )
for item in itemObj:
if re.search('eth0', item['key_']):
print item['itemid']

createUserDefinedFunction : if already exists?

I'm using azure-documentdb java SDK in order to create and use "User Defined Functions (UDFs)"
So from the official documentation I finally find the way (with a Java client) on how to create an UDF:
String regexUdfJson = "{"
+ "id:\"REGEX_MATCH\","
+ "body:\"function (input, pattern) { return input.match(pattern) !== null; }\","
+ "}";
UserDefinedFunction udfREGEX = new UserDefinedFunction(regexUdfJson);
getDC().createUserDefinedFunction(
myCollection.getSelfLink(),
udfREGEX,
new RequestOptions());
And here is a sample query :
SELECT * FROM root r WHERE udf.REGEX_MATCH(r.name, "mytest_.*")
I had to create the UDF one time only because I got an exception if I try to recreate an existing UDF:
DocumentClientException: Message: {"Errors":["The input name presented is already taken. Ensure to provide a unique name property for this resource type."]}
How should I do to know if the UDF already exists ?
I try to use "readUserDefinedFunctions" function without success. Any example / other ideas ?
Maybe for the long term, should we suggest a "createOrReplaceUserDefinedFunction(...)" on azure feedback
You can check for existing UDFs by running query using queryUserDefinedFunctions.
Example:
List<UserDefinedFunction> udfs = client.queryUserDefinedFunctions(
myCollection.getSelfLink(),
new SqlQuerySpec("SELECT * FROM root r WHERE r.id=#id",
new SqlParameterCollection(new SqlParameter("#id", myUdfId))),
null).getQueryIterable().toList();
if (udfs.size() > 0) {
// Found UDF.
}
An answer for .NET users.
`var collectionAltLink = documentCollections["myCollection"].AltLink; // Target collection's AltLink
var udfLink = $"{collectionAltLink}/udfs/{sampleUdfId}"; // sampleUdfId is your UDF Id
var result = await _client.ReadUserDefinedFunctionAsync(udfLink);
var resource = result.Resource;
if (resource != null)
{
// The UDF with udfId exists
}`
Here _client is Azure's DocumentClient and documentCollections is a dictionary of your documentDb collections.
If there's no such UDF in the mentioned collection, the _client throws a NotFound exception.

Alfresco CMIS query return objectId that contains semi-colon and version

I'm using alfresco 4.2 with OpenCMIS java client library CMIS 1.1.
String serviceUrl = "http://URL/alfresco/api/-default-/public/cmis/versions/1.1/atom"; // Uncomment for Web Services binding
// default factory implementation
SessionFactory factory = SessionFactoryImpl.newInstance();
Map<String, String> parameter = new HashMap<String, String>();
// user credentials
parameter.put(SessionParameter.USER, "admin");
parameter.put(SessionParameter.PASSWORD, "admin");
// connection settings
parameter.put(SessionParameter.ATOMPUB_URL, serviceUrl); // Uncomment for Atom Pub binding
parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value()); // Uncomment for Atom Pub binding
// Set the alfresco object factory
// Used when using the CMIS extension for Alfresco for working with aspects
List<Repository> repositories = factory.getRepositories(parameter);
Session session = repositories.get(0).createSession();
// Get some repository info
System.out.println("Repository Name: "+session.getRepositoryInfo().getName());
System.out.println("Repository ID: "+session.getRepositoryInfo().getId());
System.out.println("CMIS Version: "+session.getRepositoryInfo().getCmisVersion());
List<String> cmisObjectId = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
sb.append("select * from ged:document m");
// execute query
ItemIterable<QueryResult> results = session.query(sb.toString(), false);
for (QueryResult qResult : results) {
PropertyData<?> propData = qResult.getPropertyById("cmis:objectId");
String objectId = (String) propData.getFirstValue();
cmisObjectId.add(objectId);
System.out.println(objectId);
}
The result is :
e8137d5d-cf50-41c4-844a-ec98a44ee73a;1.0
f86557af-89c3-4287-85c4-381e47896c1a;1.0
d56b4e1e-e1dc-4514-9bd2-24080b7879a8;1.0
59a0a9a8-8309-43b6-8040-bb3e9e448171;1.0
But I would like the id of the node without the version number, to use it for REST API Call.
Thanks.
The CMIS Object ID is defined as being an opaque string. The format will differ between repository implementations, and may differ between versions of a repository.
If you want the Alfresco NodeRef, and you're sure you're talking to an Alfresco server, then the property you'll want is alfcmis:nodeRef
If you connect to your repository with the Apache Chemistry CMIS Workbench, you can see the properties it reports, and from there see things like this

Test WebSocket in PlayFramework

I have a WebSocket in my Play application and I want to write a test for it, but I couldn't find any example on how to write such a test. I found a discussion in the play-framework Google group but there has been no activity recently.
So, are there any ideas on how to test WebSocket's in a Java test?
You can retrieve underlying Iteratee,Enumerator and test them directly. This way you don't need to use a browser. You need akka-testkit though, to cope with asynchronous nature of iteratees.
A Scala example:
object WebSocket extends Controller {
def websocket = WebSocket.async[JsValue] { request =>
Future.successful(Iteratee.ignore[JsValue] -> Enumerator.apply[JsValue](Json.obj("type" -> "error")))
}
}
class WebSocketSpec extends PlaySpecification {
"WebSocket" should {
"respond with error packet" in new WithApplication {
val request = FakeRequest()
var message: JsValue = null
val iteratee = Iteratee.foreach[JsValue](chunk => message = chunk)(Akka.system.dispatcher)
Controller.websocket().f(request)(Enumerator.empty[JsValue],iteratee)
TestKit.awaitCond(message == Json.obj("type" -> "error"), 1 second)
}
}
}
I test WebSockets code using Firefox:
https://github.com/schleichardt/stackoverflow-answers/commit/13d5876791ef409e092e4a097f54247d851e17dc#L8R14
For Java it works similar replacing 'HTMLUNIT' with 'FIREFOX': http://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Chrome provides a plugin to test websocket service.
Edit
So using the plugin (as shown in picture below) you can provide websocket url and the request data and send message to service. And message log shows the message sent from client and also service response.
Assume that you have a websocket library that returns the Future[Itearatee[JsValue, Unit], Enumerator[JsValue]] your controller uses
trait WSLib {
def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
}
And you wanna test this library.
Here is a context you can use:
trait WebSocketContext extends WithApplication {
val aSecond = FiniteDuration(1, TimeUnit.SECONDS)
case class Incoming(iteratee: Iteratee[JsValue, Unit]) {
def feed(message: JsValue) = {
iteratee.feed(Input.El(message))
}
def end(wait: Long = 100) = {
Thread.sleep(wait) //wait until all previous fed messages are handled
iteratee.feed(Input.EOF)
}
}
case class OutGoing(enum: Enumerator[JsValue]) {
val messages = enum(Iteratee.fold(List[JsValue]()) {
(l, jsValue) => jsValue :: l
}).flatMap(_.run)
def get: List[JsValue] = {
Await.result(messages, aSecond)
}
}
def wrapConnection(connection: => Future[Iteratee[JsValue, Unit], Enumerator[JsValue]]): (Incoming, OutGoing) = {
val (iteratee, enumerator) = Await.result(conn, aSecond)
(Incoming(iteratee), OutGoing(enumerator))
}
}
Then your tests can be written as
"return all subscribers when asked for info" in new WebSocketContext {
val (incoming, outgoing) = wrapConnection(myWSLib.connect)
incoming.feed(JsObject("message" => "hello"))
incoming.end() //this closes the connection
val responseMessages = outgoing.get //you only call this "get" after the connection is closed
responseMessages.size must equalTo(1)
responseMessages must contain(JsObject("reply" => "Hey"))
}
Incoming represent the messages coming from the client side, while the outgoing represents the messages sent from the server. To write test, you first feed in the incoming messages from incoming and then close the connection by calling incoming.end, then you get the complete list of outgoing messages from the outgoing.get method.

Categories

Resources