[Attempto] A RESTful api for AceWiki

Changyuan Yu reivzy at gmail.com
Wed Dec 7 12:53:10 CET 2011


Before show how the RESTful api works, I want to make some explanation
about the changes of the code.

1. Using APESocket instead of APELocal to call APE. On my
system(Gentoo amd64), every time upgrade swi-prolog, I must
reconfigure tomcat to make JPL work(libjpl.so location changes). And
if I compile swi-prolog as static binary and library, then tomcat will
crash. Current code initialize APESocket with fix host and port(port
2766 on localhost), so an instance of ape.exe must run in socket
server mode to make AceWiki work.

2. Make the war be able to deployed in an OSGi container
(apache-karaf), compare to tomcat, apache-karaf is easier to use. I
can start, stop and re-deploy the war in karaf shell. To achieve this
goal, I modify the build.xml to add some information into
META-INF/MANIFEST.MF during build process.

3. Create a  servlet(RestServlet), which accept all AceWikiServlet
init parameters, and will handle all RESTful request. The servlet will
do all initialization(create ontology, save parameters, etc.) except
UI, store those initialized object into an object of class Backend,
and the store the object(of Backend class) into servlet context to
share with AceWikiServlet.

4. Mofidy AceWikiServlet and related class, first get an object of
Backend class(call it backend) from servlet context(use "backend"
paramter to determine from which RestServlet), then using ontology,
parameters and other objects from backend to create new classes.

5. Modify WEB-INF/web.xml, create two servlet instance of class
RestServlet, provide Backend object for two AceWikiServlet. Move all
parameters from AceWikiServlet to RestServlet, and add "backend"
parameter to AceWikiServlet with its value equal to corresponding
RestServlet name.

6. All actual wiki functions are done in Handler class. Current
implementation borrow a lot of code from UI part of AceWiki, and mix
wiki content maintain function with JSON object generation for fast
implementation.  There should be an spec of high level AceWiki content
maintain functions(and be implemented independent of actual UI), and
the RESTful web service should build up on this spec(we can see this
as another kind of "UI"). The web UI can also build up on the RESTful
api with ajax.


Now, I will show the detail of how to deploy the war and test the RESTful api:

First, build and deploy acewiki,
1. Install necessary tools, including git, java, ant and curl, and
also ape.exe.
2. clone dev branch of  AceWiki: git clone
https://github.com/yuchangyuan/AceWiki.git -b dev
3. build the war with command "ant",  and file "acewiki.war" will be
created after the build process.
4. deploy the war into any servlet container(tomcat, jetty,
apache-karaf etc), no need of special settings.
5. run ape.exe as socket server.
6. test AceWiki, when deploy in apache-karaf, the first demo wiki will
be on URL: localhost:8181/acewiki/acewiki/, other container may be has
a different URL.
  7. add some word and statement to AceWiki.

Then, using curl command to test RESTful api,

1. when deploy in apache-karaf, the URL of first demo wiki should be
on URL: localhost:8181/acewiki/api/ (other container may be has a
different URL). For simplicity, I will just use this URL in following
commands.

2. List all words, GET on root of URL will list all articles or search
by word. Just using command "curl localhost:8181/acewiki/api/" to list
all articles, if the wiki is empty, below result will return:

{
  "result": "ok",
  "0": {
    "word": [],
    "type": "mainpage"
  }

where, the "0" is the id of article, "word" is the words(I think I
should rename this to "words") of the article, and "type" is the type
of the article. Below is a more complex return with more words(and
more type):

{
  "result": "ok",
  "13": {
    "word": [
      "byte",
      "bytes"
    ],
    "type": "Noun"
  },
  "11": {
    "word": [
      "directory",
      "directories"
    ],
    "type": "Noun"
  },
  "12": {
    "word": [
      "file",
      "files"
    ],
    "type": "Noun"
  },
  "3": {
    "word": [
      "test-object1",
      "test-object1",
      "test-object1",
      "test-object1"
    ],
    "type": "Proper Name"
  },
  "2": {
    "word": [
      "test-object",
      "test-objects"
    ],
    "type": "Noun"
  },
  "1": {
    "word": [
      "object",
      "objects"
    ],
    "type": "Noun"
  },
  "10": {
    "word": [
      "apple",
      "apples"
    ],
    "type": "Noun"
  },
  "0": {
    "word": [],
    "type": "mainpage"
  },
  "7": {
    "word": [
      "color",
      "colors"
    ],
    "type": "Noun"
  },
  "6": {
    "word": [
      "path of"
    ],
    "type": "Of-Construct"
  },
  "5": {
    "word": [
      "Dir1",
      "Dir1",
      "Dir1",
      "Dir1"
    ],
    "type": "Proper Name"
  },
  "4": {
    "word": [
      "has",
      "have",
      "had by"
    ],
    "type": "Verb"
  },
  "9": {
    "word": [
      "color of"
    ],
    "type": "Of-Construct"
  },
  "8": {
    "word": [
      "red",
      "reds"
    ],
    "type": "Noun"
  }
}


For words search, just using 'search' as query key. For example,
search "by" with command
"curl 'localhost:8181/acewiki/api/?search=by'", will return
{
  "result": "ok",
  "4": {
    "word": [
      "has",
      "have",
      "had by"
    ],
    "type": "Verb"
  },
  "13": {
    "word": [
      "byte",
      "bytes"
    ],
    "type": "Noun"
  }
}


3. Add statement, POST on an article to add a statement to the
article. The POST using a json encoded input data as argument. For
example,  command:

curl -X POST localhost:8181/acewiki/api/0 -d '{"statement":"comment
1", "comment":true, "commit":true, "position":2}'

will create a comment "comment 1" as second statement of main page,
because main page has the id of 0, so I append 0 to the URL, and I
want to add the statement, so set "commit" to true. The return of
above command is:

{
  "position": 2,
  "result": "ok",
  "valid": true,
  "complete": true,
  "candidates": {}
}

because input "position" might be larger than total statement number
or be negative number (position from last statement), the return
"position" will show the actual position of newly created comment.

For sentence, the "commit" has not yet be implemented(always treat as
false), but we can use it to find next possible word of a partial
sentence, or check whether a sentence is valid. For example, command

curl -X POST localhost:8181/acewiki/api/0 -d '{"statement":""}'

will return a list of possible words to start a sentence, the return
will looks like:

{
  "position": -1,
  "result": "ok",
  "valid": true,
  "remain": "",
  "complete": false,
  "tokens": [],
  "candidates": {
    "": [
      "less than",
      "somebody",
      "there are",
      "every",
      "an",
      "at most",
      "which",
      "no",
      "a",
      "nothing",
      "what",
      "for every",
      "more than",
      "everything",
      "it is false that",
      "if",
      "exactly",
      "everybody",
      "there is",
      "something",
      "at least",
      "who",
      "nobody"
    ],
    "propername": [
      "test-object1",
      "Dir1"
    ],
    "variable": [
      "Y",
      "Z",
      "X"
    ]
  }
}

And for get next possible word after "an apple", using below command:
curl -X POST localhost:8181/acewiki/api/0 -d '{"statement":"an apple"}'
and will return:

{
  "position": -1,
  "result": "ok",
  "valid": true,
  "remain": "",
  "complete": false,
  "tokens": [
    "an",
    "apple"
  ],
  "candidates": {
    "": [
      "that",
      "who",
      "which",
      "is",
      "is not",
      "does not"
    ],
    "verbsg": [
      "has"
    ],
    "variable": [
      "Z",
      "X",
      "Y"
    ]
  }
}

Also, for test whether a sentence(or part of sentence) is valid,
curl -X POST localhost:8181/acewiki/api/0 -d '{"statement":"a apple not fruit"}'
and will return:

{
  "position": -1,
  "result": "ok",
  "valid": false,
  "remain": "not fruit",
  "complete": false,
  "tokens": [
    "a",
    "apple"
  ],
  "candidates": {}
}


Above are all what currently implemented, and maybe there are bugs.
>From now on, I will stop the java development for a while and begin to
create a simple emacs mode to interactive with the RestServlet and
test the word predictive function.


On Wed, Dec 7, 2011 at 3:50 PM, Tobias Kuhn <kuhntobias at gmail.com> wrote:
> Hi,
>
>>   After several days of trying AceWiki and reading its code, I want to
>> share some feelings and ideas about AceWiki.
>
>
> Thanks for sharing! It looks very interesting.
>
>
>>   In order to make this happen, AceWiki should split into two part,
>> the UI part which most in ch.uzh.ifi.attempto.acewiki.gui package (or
>> call it front end) and the actual function part which do all other
>> things except UI (or call this back end part).
>
>
> Yes, you are right. Model and view and not separated as they should be. This
> wasn't a problem so far, because there was only one GUI, but it's not so
> nice conceptually.
>
>
>>   So I fork AceWiki on github and begin to implement my ideas, I
>> choose RESTful style api for expose the wiki function, and now below
>> functions are implemented(just verified using very simple test),
>> 1. list all articles or search by word.
>> 2. add comment to an article.
>> 3. find candidate words for a partial sentence.
>
>
> Very nice! Can you give a couple of concrete examples?
>
>
>> And finally, the code: https://github.com/yuchangyuan/AceWiki/tree/dev
>
>
> For those interested, this page shows the changes to the latest version of
> AceWiki:
> https://github.com/yuchangyuan/AceWiki/compare/AceWiki:master...yuchangyuan:dev
>
>
> Regards,
> Tobias


More information about the attempto mailing list