You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2011/05/31 16:00:53 UTC
svn commit: r1129681 - in /activemq/activemq-apollo/trunk: apollo-web/pom.xml
apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala
apollo-website/src/documentation/management-api.md pom.xml
Author: chirino
Date: Tue May 31 14:00:53 2011
New Revision: 1129681
URL: http://svn.apache.org/viewvc?rev=1129681&view=rev
Log:
Fixes https://issues.apache.org/jira/browse/APLO-27
We now support a paged/tabular interface to accessing the management interface.
Modified:
activemq/activemq-apollo/trunk/apollo-web/pom.xml
activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala
activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md
activemq/activemq-apollo/trunk/pom.xml
Modified: activemq/activemq-apollo/trunk/apollo-web/pom.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/pom.xml?rev=1129681&r1=1129680&r2=1129681&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/pom.xml (original)
+++ activemq/activemq-apollo/trunk/apollo-web/pom.xml Tue May 31 14:00:53 2011
@@ -90,7 +90,19 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
-
+
+ <dependency>
+ <groupId>net.sf.josql</groupId>
+ <artifactId>josql</artifactId>
+ <version>${josql-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.josql</groupId>
+ <artifactId>gentlyweb-utils</artifactId>
+ <version>${josql-version}</version>
+ </dependency>
+
+
<!-- Scala Support -->
<dependency>
<groupId>org.scala-lang</groupId>
Modified: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala?rev=1129681&r1=1129680&r2=1129681&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala Tue May 31 14:00:53 2011
@@ -16,18 +16,22 @@
*/
package org.apache.activemq.apollo.web.resources;
-import javax.ws.rs._
-import core.Response
-import Response.Status._
import org.apache.activemq.apollo.dto._
import java.{lang => jl}
import org.fusesource.hawtdispatch._
import org.apache.activemq.apollo.broker._
import scala.collection.Iterable
-import org.apache.activemq.apollo.util.{Failure, Success, Dispatched, Result}
import scala.Some
import security.{SecurityContext, Authorizer}
import org.apache.activemq.apollo.util.path.PathParser
+import org.apache.activemq.apollo.web.resources.Resource._
+import org.josql.Query
+import org.apache.activemq.apollo.util._
+import collection.mutable.ListBuffer
+import javax.ws.rs._
+import core.Response
+import Response.Status._
+import org.josql.expressions.SelectItemExpression
/**
* <p>
@@ -222,6 +226,45 @@ case class BrokerResource() extends Reso
link
}
+ def narrow[T](kind:Class[T], x:Iterable[Result[T, Throwable]], f:java.util.List[String], q:String, p:java.lang.Integer, ps:java.lang.Integer) = {
+ import collection.JavaConversions._
+ try {
+ var records = x.toSeq.flatMap(_.success_option)
+
+ val page_size = if( ps !=null ) ps.intValue() else 100
+ val page = if( p !=null ) p.intValue() else 0
+
+ val query = new Query
+ val fields = if (f.isEmpty) "*" else f.toList.mkString(",")
+ val where_clause = if (q != null) q else "1=1"
+
+ query.parse("SELECT " + fields + " FROM " + kind.getName + " WHERE "+ where_clause+" LIMIT "+((page_size*page)+1)+", "+page_size)
+ val headers = if (f.isEmpty) seqAsJavaList(List("*")) else f
+
+ val list = query.execute(records).getResults
+
+ Success(seqAsJavaList( headers :: list.toList) )
+ } catch {
+ case e:Throwable => Failure(e)
+ }
+ }
+
+ @GET @Path("virtual-hosts/{id}/topics")
+ @Produces(Array("application/json"))
+ def topics(@PathParam("id") id : String, @QueryParam("f") f:java.util.List[String],
+ @QueryParam("q") q:String, @QueryParam("p") p:java.lang.Integer, @QueryParam("ps") ps:java.lang.Integer ):java.util.List[_] = {
+ with_virtual_host(id) { host =>
+ val router: LocalRouter = host
+ val records = Future.all {
+ router.topic_domain.destination_by_id.values.map { value =>
+ status(value)
+ }
+ }
+ val rc:FutureResult[java.util.List[_]] = records.map(narrow(classOf[TopicStatusDTO], _, f, q, p, ps))
+ rc
+ }
+ }
+
@GET @Path("virtual-hosts/{id}/topics/{name:.*}")
def topic(@PathParam("id") id : String, @PathParam("name") name : String):TopicStatusDTO = {
with_virtual_host(id) { host =>
@@ -231,6 +274,23 @@ case class BrokerResource() extends Reso
}
}
+ @GET @Path("virtual-hosts/{id}/queues")
+ @Produces(Array("application/json"))
+ def queues(@PathParam("id") id : String, @QueryParam("f") f:java.util.List[String],
+ @QueryParam("q") q:String, @QueryParam("p") p:java.lang.Integer, @QueryParam("ps") ps:java.lang.Integer ):java.util.List[_] = {
+ with_virtual_host(id) { host =>
+ val router: LocalRouter = host
+ val values: Iterable[Queue] = router.queue_domain.destination_by_id.values
+
+ val records = sync_all(values) { value =>
+ status(value, false)
+ }
+
+ val rc:FutureResult[java.util.List[_]] = records.map(narrow(classOf[QueueStatusDTO], _, f, q, p, ps))
+ rc
+ }
+ }
+
@GET @Path("virtual-hosts/{id}/queues/{name:.*}")
def queue(@PathParam("id") id : String, @PathParam("name") name : String, @QueryParam("entries") entries:Boolean ):QueueStatusDTO = {
with_virtual_host(id) { host =>
@@ -240,6 +300,22 @@ case class BrokerResource() extends Reso
}
}
+ @GET @Path("virtual-hosts/{id}/dsubs")
+ @Produces(Array("application/json"))
+ def durable_subscriptions(@PathParam("id") id : String, @QueryParam("f") f:java.util.List[String],
+ @QueryParam("q") q:String, @QueryParam("p") p:java.lang.Integer, @QueryParam("ps") ps:java.lang.Integer ):java.util.List[_] = {
+ with_virtual_host(id) { host =>
+ val router: LocalRouter = host
+ val values: Iterable[Queue] = router.topic_domain.durable_subscriptions_by_id.values
+
+ val records = sync_all(values) { value =>
+ status(value, false)
+ }
+
+ val rc:FutureResult[java.util.List[_]] = records.map(narrow(classOf[QueueStatusDTO], _, f, q, p, ps))
+ rc
+ }
+ }
@GET @Path("virtual-hosts/{id}/dsubs/{name:.*}")
def durable_subscription(@PathParam("id") id : String, @PathParam("name") name : String, @QueryParam("entries") entries:Boolean):QueueStatusDTO = {
with_virtual_host(id) { host =>
@@ -377,27 +453,30 @@ case class BrokerResource() extends Reso
}
}
-
@GET @Path("connections")
- def connections:LongIdListDTO = {
+ @Produces(Array("application/json"))
+ def connections(@QueryParam("f") f:java.util.List[String], @QueryParam("q") q:String,
+ @QueryParam("p") p:java.lang.Integer, @QueryParam("ps") ps:java.lang.Integer ):java.util.List[_] = {
+
with_broker { broker =>
monitoring(broker) {
- val rc = new LongIdListDTO
+ val values = ListBuffer[BrokerConnection]()
broker.connectors.foreach { connector=>
- connector.connections.foreach { case (id,connection) =>
- // TODO: may need to sync /w connection's dispatch queue
- rc.items.add(new LongIdLabeledDTO(id, connection.transport.getRemoteAddress ))
- }
+ values ++= connector.connections.values
+ }
+ val records = sync_all(values) { value =>
+ value.get_connection_status
}
+ val rc:FutureResult[java.util.List[_]] = records.map(narrow(classOf[ConnectionStatusDTO], _, f, q, p, ps))
rc
}
}
}
@GET @Path("connections/{id}")
- def connections(@PathParam("id") id : Long):ConnectionStatusDTO = {
+ def connection(@PathParam("id") id : Long):ConnectionStatusDTO = {
with_connection(id){ connection=>
monitoring(connection.connector.broker) {
connection.get_connection_status
Modified: activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md?rev=1129681&r1=1129680&r2=1129681&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md (original)
+++ activemq/activemq-apollo/trunk/apollo-website/src/documentation/management-api.md Tue May 31 14:00:53 2011
@@ -39,6 +39,92 @@ Example:
$ curl -u "admin:password" http://localhost:61680/broker.json
+### Working with Tabular Results
+
+Many of the resource routes provided by the broker implement
+a selectable paged tabular interface. A good example of such
+a resource route is the connections list. It's route is:
+
+ /broker/connections
+
+Example:
+
+ $ curl -u "admin:password" \
+ 'http://localhost:61680/broker/connections.json'
+ [
+ [
+ "*"
+ ],
+ {
+ "id":"4",
+ "state":"STARTED",
+ "state_since":1306848325102,
+ "read_counter":103,
+ "write_counter":239110628,
+ "transport":"tcp",
+ "protocol":"stomp",
+ "remote_address":"/127.0.0.1:61775",
+ "protocol_version":"1.0",
+ "user":"admin",
+ "waiting_on":"client request",
+ "subscription_count":1
+ },
+ {
+ "id":"5",
+ "state":"STARTED",
+ "state_since":1306848325102,
+ "read_counter":227739229,
+ "write_counter":113,
+ "transport":"tcp",
+ "protocol":"stomp",
+ "remote_address":"/127.0.0.1:61776",
+ "protocol_version":"1.0",
+ "user":"admin",
+ "waiting_on":"blocked sending to: org.apache.activemq.apollo.broker.Queue$$anon$1@13765e9b",
+ "subscription_count":0
+ }
+ ]
+
+The results are an array of records with the first record acting as a header
+records describing the fields selected. The `*` field means all the record's
+fields were selected. To narrow down the selected fields you can add
+multiple `f` query parameters to pick the fields you want to retrieve.
+
+Example:
+ $ curl -u "admin:password" \
+ 'http://localhost:61680/broker/connections.json?f=id&f=read_counter'
+ [
+ [
+ "id",
+ "read_counter"
+ ],
+ [
+ "7",
+ 110733109
+ ],
+ [
+ "6",
+ 103
+ ]
+ ]
+
+If you want to narrow down the records which get selected, you can set a `q`
+query parameter to SQL 92 style where clause which uses the record's fields
+to filter down the selected records.
+
+For example to only view local connection, you would want to use a where
+clause like `remote_address LIKE "/127.0.0.01:%"` which to execute with
+`curl` you would run:
+
+ curl -u "admin:password" \
+ 'http://localhost:61680/broker/connections.json?q=remote_address%20LIKE%20"/127.0.0.1:%"'
+
+The records are paged. The default page size is 100, so only the first 100
+records will be displayed. If you want to view subsequent results, you must
+set the `p` query parameter to the page you wish to access. You can change
+the page size by setting the `ps` query parameter.
+
+
### Broker Management
The route for managing the broker is:
@@ -107,7 +193,11 @@ Results in a [Connector Status](./api/ap
### Connection Management
-The route for managing a connection is:
+The route for getting a tabular list of connections is:
+
+ /broker/connections
+
+The route for managing a single connection is:
/broker/connections/:id
@@ -226,6 +316,10 @@ Results in a [Store Status](./api/apollo
#### Queue Management
+The route for getting a tabular list of queues is:
+
+ /broker/virtual-hosts/:name/queues
+
The route for managing a virtual host's Queue is:
/broker/virtual-hosts/:name/queues/:qid
@@ -295,6 +389,10 @@ Results in a [Queue Status](./api/apollo
#### Topic Management
+The route for getting a tabular list of queues is:
+
+ /broker/virtual-hosts/:name/topics
+
The route for managing a virtual host's Topic is:
/broker/virtual-hosts/:name/topics/:tid
@@ -337,6 +435,28 @@ Results in a [Topic Status](./api/apollo
}
{pygmentize}
+
+#### Durable Subscription Management
+
+The route for getting a tabular list of durable subscriptions is:
+
+ /broker/virtual-hosts/:name/dsubs
+
+The route for managing a virtual host's durable subscription is:
+
+ /broker/virtual-hosts/:name/dsubs/:sub
+
+Where `:name` is the id of a virtual host configured in the broker and `:sub` is the id
+of the durable subscription.
+
+Example:
+
+ $ curl -u "admin:password" \
+ http://localhost:61680/broker/virtual-hosts/localhost/dsubs/mysub.json
+
+Results in a [Queue Status](./api/apollo-dto/org/apache/activemq/apollo/dto/QueueStatusDTO.html):
+
+
### Getting the Broker's Configuration
To get current runtime configuration of the broker GET:
Modified: activemq/activemq-apollo/trunk/pom.xml
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/pom.xml?rev=1129681&r1=1129680&r2=1129681&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/pom.xml (original)
+++ activemq/activemq-apollo/trunk/pom.xml Tue May 31 14:00:53 2011
@@ -122,6 +122,7 @@
<cascal-version>1.3-SNAPSHOT</cascal-version>
<hawtdb-version>1.6-SNAPSHOT</hawtdb-version>
+ <josql-version>1.5</josql-version>
<!-- osgi stuff -->
<osgi-version>4.2.0</osgi-version>
@@ -739,7 +740,15 @@
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
-
+
+ <!-- for net.sf.josql dependency not yet in central -->
+ <repository>
+ <id>com.fusesource.m2</id>
+ <url>http://repo.fusesource.com/nexus/content/groups/public/</url>
+ <releases><enabled>true</enabled></releases>
+ <snapshots><enabled>false</enabled></snapshots>
+ </repository>
+
</repositories>
<pluginRepositories>