Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tag group with name containing "-" hyphen breaks read op #37

Open
tblong opened this issue Aug 16, 2023 · 4 comments
Open

Tag group with name containing "-" hyphen breaks read op #37

tblong opened this issue Aug 16, 2023 · 4 comments
Assignees

Comments

@tblong
Copy link

tblong commented Aug 16, 2023

nHaystack version: v3.2.0
Niagara N4 v4.12.2.16

The Issue

Creating a tag dictionary, then a tag group where the tag group name is e.g. "valve-Actuator", causes any read op filter query to return Invalid tag name: valve$2dActuator" errTrace:"java.lang.IllegalArgumentException. Full stack trace below. The tag group appears to be treated as a tag itself when its merely a container for other tags.

Steps to reproduce

  1. Add a new smart tag dictionary to a station with the configuration in the screenshot below.
    image
  2. Create a control point in the station and add the tag group "valve-Actuator" as a direct tag to to the control point.
  3. Run the following read op query against the station: https://localhost/haystack/read?filter=point
  4. Expect the following stack trace and errors to show up:
ver:"3.0" dis:"java.lang.IllegalArgumentException: Invalid tag name: valve$2dActuator" errTrace:"java.lang.IllegalArgumentException: Invalid tag name: valve$2dActuator
  at org.projecthaystack.HDictBuilder.add(HDictBuilder.java:79)
  at nhaystack.server.TagManager.generateComponentTags(TagManager.java:296)
  at nhaystack.server.TagManager.createComponentTags(TagManager.java:463)
  at nhaystack.server.SpaceManager$CIterator.findNext(SpaceManager.java:230)
  at nhaystack.server.SpaceManager$CIterator.next(SpaceManager.java:211)
  at nhaystack.server.SpaceManager$CIterator.next(SpaceManager.java:190)
  at nhaystack.collection.CompositeIterator.findNext(CompositeIterator.java:67)
  at nhaystack.collection.CompositeIterator.next(CompositeIterator.java:39)
  at org.projecthaystack.server.HServer.onReadAll(HServer.java:115)
  at nhaystack.server.NHServer.onReadAll(NHServer.java:120)
  at org.projecthaystack.HProj.readAll(HProj.java:141)
  at org.projecthaystack.server.ReadOp.onService(HStdOps.java:149)
  at org.projecthaystack.server.HOp.onService(HOp.java:48)
  at org.projecthaystack.server.HServlet.onService(HServlet.java:90)
  at org.projecthaystack.server.HServlet.doGet(HServlet.java:47)
  at nhaystack.server.BNHaystackServlet.doGet(BNHaystackServlet.java:79)
  at javax.baja.web.BWebServlet.service(BWebServlet.java:152)
  at javax.baja.web.BWebServlet.doService(BWebServlet.java:198)
  at javax.baja.web.BWebServlet.access$000(BWebServlet.java:50)
  at javax.baja.web.BWebServlet$Servlet.doGet(BWebServlet.java:329)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
  at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
  at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656)
  at com.tridium.web.filters.WebStartServletFilter.doFilter(WebStartServletFilter.java:47)
  at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
  at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
  at com.tridium.web.filters.ContextFilter.doFilter(ContextFilter.java:42)
  at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
  at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
  at com.tridium.web.filters.LocaleFilter.doFilter(LocaleFilter.java:31)
  at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
  at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
  at com.tridium.web.filters.TridiumSecurityFilter.doFilter(TridiumSecurityFilter.java:42)
  at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
  at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
  at com.tridium.web.filters.AddSubjectFilter.lambda$null$0(AddSubjectFilter.java:58)
  at java.security.AccessController.doPrivileged(Native Method)
  at javax.security.auth.Subject.doAs(Subject.java:422)
  at com.tridium.web.filters.AddSubjectFilter.lambda$doFilter$1(AddSubjectFilter.java:57)
  at java.security.AccessController.doPrivileged(Native Method)
  at com.tridium.web.filters.AddSubjectFilter.doFilter(AddSubjectFilter.java:55)
  at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
  at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
  at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
  at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
  at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560)
  at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
  at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
  at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
  at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
  at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
  at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
  at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
  at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
  at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
  at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
  at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
  at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:234)
  at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
  at com.tridium.jetty.NiagaraSecurityHandler.handle(NiagaraSecurityHandler.java:76)
  at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
  at org.eclipse.jetty.server.Server.handle(Server.java:516)
  at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
  at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
  at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
  at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
  at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
  at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
  at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:555)
  at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:410)
  at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:164)
  at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
  at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
  at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
  at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
  at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
  at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
  at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
  at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
  at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
  at com.tridium.nre.util.PrivilegedRunnable.lambda$run$0(PrivilegedRunnable.java:30)
  at java.security.AccessController.doPrivileged(Native Method)
  at com.tridium.nre.util.PrivilegedRunnable.run(PrivilegedRunnable.java:28)
  at java.lang.Thread.run(Thread.java:750)
" err

Additional Coments

Note that when I rename the tag group from "valve-Actuator" to "valveActuator" then the read op succeeds as expected. What is unexpected is that the control point on which the tag group "valveActuator" added, the resulting read op returns "valveActuator" as a marker tag to the control point. The tag group is unexpectedly getting treated as a maker tag.

@tblong tblong changed the title Tag group with name containing "-" hyphen breaks filter query Tag group with name containing "-" hyphen breaks read op Aug 16, 2023
@ci-richard-mcelhinney ci-richard-mcelhinney self-assigned this Aug 16, 2023
@ci-richard-mcelhinney
Copy link
Owner

Hi @tblong ,

Thanks for your feedback here. I think there are 2 parts to your issue. The first part is about tag and tag group naming. The actual exception here is coming not from nhaystack code but from the haystack-java reference library. This is because in the Project Haystack standard using a '-' in the tag name is invalid. I'm surprised that Niagara allows it.

The rules for tag naming: https://project-haystack.org/doc/docHaystack/Kinds#names

With regards to the second part of your question about how nhaystack handles the expansion of tag groups in Niagara I'm going to need to think about that some more.

I'll come back to you once I have done some investigation.

@tblong
Copy link
Author

tblong commented Aug 17, 2023

@ci-richard-mcelhinney Thanks much for the help here.

My assumption is that the nhaystack side will likely have to defensively prevent the call to HDictBuilder.add(HDictBuilder.java:79) when it encounters a tag group; but not the tags contained in the tag group. Such that the tag group itself is not added as a tag and also not flagged with naming violations which do not follow the Haystack standard.

@ci-richard-mcelhinney
Copy link
Owner

@esanderson can you please comment on the rules Niagara enforces for tag names? Is it just he same rules as slot names? If so there might be a difference here we need to reconcile.

@esanderson
Copy link
Collaborator

We are not doing much enforcement on tag or tag group names beyond the rules for slot names. We do enforce that no tag name is equal to a tag group name and vice-versa. We should be doing more enforcement, however, because NEQL only supports names that start with a letter and contain letters, digits, underbar, and dot (entered a Tridium defect for this). We may not enforce that tag names must start with a lower case letter as required by Project Haystack. Supporting the dot (a rare case, probably) would violate Haystack rules. Would be nice if the dictionary could enforce stricter rules than enforced for all tag names in Niagara (noted on the Tridium defect).

Regarding the behavior of tag groups, they are mostly a container for other tags. However, Niagara also implies a marker tag that is the tag group name. That implied would be exported over nhaystack in addition to the tags in the tag group.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants