#579 Haystack-Java by Brian Frank

Aamir Khan Mon 5 Feb 2018

Hi,

I am trying to build the project and getting the issue.

org.projecthaystack.client.ClientTest.setup FAILED

org.projecthaystack.auth.AuthException at ClientTest.java:37
    Caused by: java.net.ConnectException at ClientTest.java:37

Results: FAILURE (141 tests, 0 successes, 1 failures, 140 skipped)

141 tests completed, 1 failed, 140 skipped :test FAILED

FAILURE: Build failed with an exception.

Please help me to resolve the issue.

Matthew Giannini Tue 6 Feb 2018

You can ignore that test; it will fail unless you have a Haystack Server running for it to connect to. I need to find a way to skip that test by default. It's more like an integration test.

Aamir Khan Tue 6 Feb 2018

I am getting error while running the Script ./gradlew build.

org.projecthaystack.client.ClientTest.setup FAILED

So there is no go unless I successfully build the project.

Aamir Khan Tue 6 Feb 2018

I built the project successfully after I removed the src/test folder.Build was successful but I didn't get any executable files.

Please let me know if something else is needed to be done.

Abhay Nayak Tue 6 Feb 2018

Having same issue, do we need to edit or write something to enable the client server executables?

Steve Eynon Wed 7 Feb 2018

I built the project successfully after I removed the src/test folder.

As it was only ClientTest.java that was failing, you only needed to delete that one test, but I guess deleting the entire test directory also works.

I didn't get any executable files.

Perhaps there's some confusion. The haystack-java library is a Java library. Building it creates a .jar file which provides an API for you to use in your Java programs. A successful build should produce:

/build/lib/haystack-java-3.0.0-SNAPSHOT.jar

There are no .exe executables, client or server.

There is a HttpServlet class though, should you wish to create your own Java web application.

Ashish Belagali Wed 7 Feb 2018

The challenge with the java code is that no servlet is exposed through it, and hence all commands return 404.

Here is how to resolve this problem (and also upgrade to the recent versions of the technology stack):

(1) Add the annotation @WebServlet("/*") on a line before the class definition in HServlet. Thus, the two lines now become:

@WebServlet("/*") public class HServlet extends HttpServlet

Add the import in the import section

import javax.servlet.annotation.WebServlet;

(2) This will not work without upgrading to the latest servlet spec. To do that, edit build.gradle and change it there. Here is the list of my complete changes which makes a few other enhancements too.

Change the top apply-plugin lines to:

plugins {

id 'java'
id 'war' 
id 'maven' 
id 'eclipse'

}

Change the source and target compatibility to 1.8

compileJava {

sourceCompatibility = 1.8
targetCompatibility = 1.8

}

Change the providedCompile under dependencies as:

providedCompile 'javax.servlet:javax.servlet-api:3.1.0'

You can comment out the compile line under dependencies now.

(3) In HServlet.java there is a minor problem around line 70. Correct it by using getContextPath() as below:

if (path == null || path.length() == 0 || path.equals("/"))
{
  res.sendRedirect(req.getContextPath() + "/about");
  return;
}

(4) Compile the sources now with firing the following command

gradle war

The resultant war can be deployed to a JEE compliant web container such as tomcat and responds to Haystack requests. I have checked /about and /ops.

Matthew Giannini Thu 8 Feb 2018

You can build haystack-java without having to delete any tests:

./gradlew jar

That will just build the jar file without running tests.

As far as server goes; that should probably be a separate project. I'd rather pull out the server as a separate project instead of updating this library for that. The haystack-java project is intended to provide core haystack capabilities (encodings, data types, client). A server is a whole other beast.

Ashish Belagali Fri 9 Feb 2018

Well, the gradle build file (build.gradle) already contains a war target, so it is natural to try to create a war. If this was not the intention, then I do not think the war target should have been there.

Further, the war file gets built easily with gradle war command and also gets deployed without any problem. However, it keeps giving 404 error for every request -- as the servlet is not exposed.

That's what I have corrected in the procedure given above. The war file built after identified changes responds to the various ops.

As far as the tests in ClientTest.java are concerned, they seem to be intended for the Skywire server implementation only. They fail for the war that gets built here, as it does not have inbuilt authentication.

Aamir Khan Fri 9 Feb 2018

Hi,Ashish

Did the same changes as you asked but I am still not able to response from servlet.

Type Status Report

Message /about

Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

Matthew Giannini Fri 9 Feb 2018

I just pushed a changeset that properly exposes the HServlet when you compile to a WAR. I also added a gretty dependency so you can run the server using gradle:

./gradlew appRun

Ashish - Thanks for your post to help resolve some of the issues. The only thing I didn't do was bump the java version 1.8; I did bump it to 1.7, but this project has been fairly conservative about minimum java version dependency.

Aamir Khan Sat 10 Feb 2018

Hi,Ashish

Followed the same changes still not able to host the Servlet.It is routing to /about but I am not getting any response.What could possibly be wrong now.

Tried with Matthew's changes too even though I am not getting response from server.

Aamir Khan Sat 10 Feb 2018

Hi,Matthew thanks for the updates I am able to run the server using ./gradlew appRun.

Can you please give me more informations or documentation about how was it done.Would be a great help in understanding and designing the client.

Ashish Belagali Tue 20 Feb 2018

Sorry I did not get a chance to come here for a bit. I read that Aamir had some issues in getting it running but I believe he is able to do it now.

Regarding running gradle, I have a local gradle installation on my machine and the script "gradle" is in my path. I can therefore fire a "gradle war" command and have the war file built. The "gradlew" alternative is slower in my experience.

Matthew Giannini Tue 20 Feb 2018

Yes; if you already have gradle installed that will generally work. However, the gradlew command will ensure that everyone is building using the same Gradle environment, and it doesn't require you to have a global installation. Whatever works for you.

Aamir Khan Thu 22 Feb 2018

Hi Matthew

I want to add two equipment with same display name.How can I do it without over-writing the existing one as because our equip-ID is generated based on our display name. Or should we expect user to give unique name for each equipment.

Kindly Help.

Brian Frank Thu 22 Feb 2018

I want to add two equipment with same display name.

As a general rule display names should be unique and understandable without context. If I do a global search for all equips, then there shouldn't be duplicates. We suggest that display names for equip are prefixed by site names, and point names are prefixed by equip display:

MySite
MySite AHU-1
MySite AHU-1 DischargeTemp

Ids must be unique. If there is any chance for the user to rename the display, then its better to use an opaque id for more robustness. Its all the same principles about deciding what to use as a primary key for a relational database (most people think is should be a auto-generated key independent from domain)

Aamir Khan Fri 23 Feb 2018

Hi, Brian

How can we add device specific informations to Haystack Structure.Suppose I want to add KNX switch informations to Haystack Structure for which there is no well defined tag,then how can I add those informations to Haystack structure.

Brian Frank Fri 23 Feb 2018

How can we add device specific informations to Haystack Structure.Suppose I want to add KNX switch informations to Haystack Structure for which there is no well defined tag,then how can I add those informations to Haystack structure.

You are free to make up your own tags on a per product or per project basis. However, the safe thing to do is make sure its unique by prefixing with it some product/org/functional prefix. Maybe in this case prefix those tags with knxFoo. You should assume that any generic tag might eventually be standardized by Haystack

Abhay Nayak Wed 7 Mar 2018

Now that we're already discussing about it here, I was going through the docs and found the HisRead and HisWrite ops but its quite obscure. HisRead as per my understanding of this following example is that a request is sent to query the history points (Correct me if wrong)

// request ver:"3.0" id,range @someTemp,"2012-10-01"

// reponse ver:"3.0" id:@someTemp hisStart:2012-10-01T00:00:00-04:00 New_York hisEnd:2012-10-02T00:00:00-04:00 New_York ts,val 2012-10-01T00:15:00-04:00 New_York,72.1°F 2012-10-01T00:30:00-04:00 New_York,74.2°F 2012-10-01T00:45:00-04:00 New_York,75.0°F ..

But I was not able to understand what HisWrite op is or how and why is it required? Can you please explain the purpose of HisWrite and HisRead

Brian Frank Wed 7 Mar 2018

HisRead is used to query/read/poll history data that is stored/collected by the Haystack host node

HisWrite is used to "push" history data, typically from an edge device to a cloud/server

Aamir Khan Fri 9 Mar 2018

Hi, Brian

I am adding my own custom operations for adding Site, equip, points. Can you tell me if I can add my custom operations apart from Haystack standard ops.

Brian Frank Fri 9 Mar 2018

You can create your own tags and own ops. Just use names which guarantee uniqueness to avoid conflicts with future standardized ops (such as prefixing with your product/company name).

Aamir Khan Thu 22 Mar 2018

Hi Brian,

1) I am implementing hisRead and pointWrite operation. I saw that hisRead is supported by points having his tag and pointWrite is by the point having cur tag. So are these tags mutually exclusive?

2) And can we have an extra Map for holding the curVal of points?This can be really helpful in case of pointWrite.

And Thanks for answering my queries :)

Brian Frank Thu 22 Mar 2018

Using hisRead requires the point to have his tag.

Using pointWrite requires the point to have the writable tag (not cur).

A given point, may have all three (cur, his, and writable).

I just want to note the philosophy here: curVal, curStatus, etc are considered part of the entity data model - they are tags on the point which you can read/subscribe to with a watch. The priority array of a writable point is assumed to be outside the entity model itself and must be queried with an op - you don't manage the priority array with a tag (although you do maintain writeVal, writeLevel as part of the entity model)

Login or Signup to reply.