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

Add Pharo 11 to the build #46

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/loading-groups.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ jobs:
strategy:
fail-fast: false
matrix:
smalltalk: [ Pharo64-10, Pharo64-9.0, Pharo64-8.0 ]
smalltalk: [ Pharo64-11, Pharo64-10, Pharo64-9.0, Pharo64-8.0 ]
load-spec: [ client-deployment, server-deployment, http-transport, tcp-transport, server-logging ]
name: ${{ matrix.smalltalk }} + ${{ matrix.load-spec }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: hpi-swa/setup-smalltalkCI@v1
with:
smalltalk-image: ${{ matrix.smalltalk }}
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
smalltalk: [ Pharo64-10, Pharo64-9.0, Pharo64-8.0, Pharo32-8.0, Pharo64-7.0, Pharo32-7.0 , Pharo32-6.1 ]
smalltalk: [ Pharo64-11, Pharo64-10, Pharo64-9.0, Pharo64-8.0, Pharo64-7.0 ]
name: ${{ matrix.smalltalk }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: hpi-swa/setup-smalltalkCI@v1
with:
smalltalk-image: ${{ matrix.smalltalk }}
Expand All @@ -20,7 +20,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
timeout-minutes: 15
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
name: ${{matrix.os}}-${{matrix.smalltalk}}
name: Unit-Tests-${{matrix.smalltalk}}
token: ${{ secrets.CODECOV_TOKEN }}
23 changes: 16 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
Contributing
============
# Contributing

There's several ways to contribute to the project: reporting bugs, sending feedback, proposing ideas for new features, fixing or adding documentation, promoting the project, or even contributing code.
There are several ways to contribute to the project: reporting bugs, sending
feedback, proposing ideas for new features, fixing or adding documentation,
promoting the project, or even contributing code.

## Reporting issues

You can report issues [here](https://github.com/juliendelplanque/JRPC/issues/new)

## Contributing Code

- This project is MIT licensed, so any code contribution MUST be under the same license.
- This project uses [Semantic Versioning](http://semver.org/), so keep it in mind when you make backwards-incompatible changes. If some backwards incompatible change is made the major version MUST be increased.
- The source code is hosted in this repository using the Tonel format in the `src` folder.
- This project uses [Semantic Versioning](http://semver.org/), so keep it in mind
when you make backwards-incompatible changes. If some backwards incompatible
change is made the major version MUST be increased.
- The source code is hosted in this repository using the Tonel format in the
`src` folder.
- The `master` branch contains the latest changes.
- Feel free to send pull requests or fork the project.

### Using Iceberg

1. Download a [Pharo Image and VM](https://get.pharo.org/64)
2. Clone the project or your fork using Iceberg
3. Open the Working Copy and using the contextual menu select `Metacello -> Install baseline...`
3. Open the Working Copy and using the contextual menu select
`Metacello -> Install baseline...`
4. Input `Development`
5. This will load the base code and the test cases
6. Create a new branch to host your code changes
Expand All @@ -28,4 +35,6 @@ You can report issues [here](https://github.com/juliendelplanque/JRPC/issues/new

## Contributing documentation

The project documentation is maintained in this repository in the `docs` folder. To contribute some documentation or improve the existing, feel free to create a branch or fork this repository, make your changes and send a pull request.
The project documentation is maintained in this repository in the `docs` folder.
To contribute some documentation or improve the existing, feel free to create a
branch or fork this repository, make your changes and send a pull request.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
[![Baseline Groups](https://github.com/juliendelplanque/JRPC/actions/workflows/loading-groups.yml/badge.svg)](https://github.com/juliendelplanque/JRPC/actions/workflows/loading-groups.yml)

[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Pharo version](https://img.shields.io/badge/Pharo-6.1-%23aac9ff.svg)](https://pharo.org/download)
[![Pharo version](https://img.shields.io/badge/Pharo-7.0-%23aac9ff.svg)](https://pharo.org/download)
[![Pharo version](https://img.shields.io/badge/Pharo-8.0-%23aac9ff.svg)](https://pharo.org/download)
[![Pharo version](https://img.shields.io/badge/Pharo-9.0-%23aac9ff.svg)](https://pharo.org/download)
[![Pharo 10](https://img.shields.io/badge/Pharo-10-%23aac9ff.svg)](https://pharo.org/download)
[![Pharo 11](https://img.shields.io/badge/Pharo-11-%23aac9ff.svg)](https://pharo.org/download)

Yet another [JSON-RPC 2.0](https://www.jsonrpc.org/specification) implementation for Pharo Smalltalk
Yet another [JSON-RPC 2.0](https://www.jsonrpc.org/specification) implementation
for [Pharo Smalltalk](https://www.pharo.org)

- [Features](#features)
- [Installation](#installation)
Expand All @@ -20,15 +21,16 @@ Yet another [JSON-RPC 2.0](https://www.jsonrpc.org/specification) implementation
- [Contributing](#contributing)

## Features

- Client and Server support for JSON-RPC 2.0.
- Only depends on Pharo's built-in packages.
- Uses STONJSON to parse JSON internally.
- Only depend on Pharo's built-in packages.
- Uses `STONJSON` to parse JSON internally.
- Transport agnostic (like JSON-RPC 2.0 spec claims).
- Can currently be used over
- HTTP
- TCP
- It is easy to add other transport layers.
- Additional `data` when an error occured in the `error` object.
- Additional `data` when an error occurred in the `error` object.

## Examples

Expand Down
74 changes: 46 additions & 28 deletions docs/Examples.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
# Examples

## Client
Given a server using HTTP protocol, listening on port 4000 and exposing `'sqrt'` method which computes the square-root of its single parameter, one can write the following:

Given a server using HTTP protocol, listening on port 4000 and exposing `'sqrt'`
method which computes the square-root of its single parameter, one can write the
following:

```Smalltalk
(JRPCClient http: 'http://localhost:4000')
callMethod: 'sqrt' arguments: #(4) withId: 1
callMethod: 'sqrt' arguments: #(4) withId: 1
```

The object returned by this expression is an instance of `JRPCSuccessResponseObject`.
Its `result` instance variable contains the result of `sqrt` method applied on `4`. That is to say, it contains `2.0`.
Its `result` instance variable contains the result of `sqrt` method applied on
`4`. That is to say, it contains `2.0`.
Its `id` instance variable contains the `id` specified previously.

Ids allow to map responses returned by the server to requests sent by the client.
Ids are managed by the developer using the client.

## Server
To create a server using HTTP protocol, listening on port 4000 and defining an handler for `'sqrt'` which computes the square-root of its single paramter, one can write the following:

To create a server using HTTP protocol, listening on port 4000 and defining a
handler for `'sqrt'` which computes the square-root of its single parameter, one
can write the following:

```Smalltalk
server := JRPCServer http
port: 4000;
addHandlerNamed: 'sqrt' block: [ :x | x sqrt ];
yourself.
port: 4000;
addHandlerNamed: 'sqrt' block: [ :x | x sqrt ];
yourself.
```

To start it, use `#start` method:
Expand All @@ -37,9 +45,16 @@ server stop
```

## Additional data provided in error messages
[JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification) specifies that in error messages, a `data` field can optionally be set to provide additional information about the error. However, this field structure is specified by the server. This section describes what the current implementation stores in the `data` field.

To do that, let's take the following configuration. We have a server defined as follow:
[JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification) specifies
that in error messages, a `data` field can optionally be set to provide additional
information about the error. However, this field structure is specified by the
server. This section describes what the current implementation stores in the
`data` field.

To do that, let's take the following configuration. We have a server defined
as follows:

```Smalltalk
server := JRPCServer http
port: 4000;
Expand All @@ -49,40 +64,43 @@ server := JRPCServer http
server start.
```

This server has a handler implenting a the division of `x` by `y`. In Pharo, dividing a `Number` by `0` results in a `ZeroDivide` error. Thus, the following code:
This server has a handler implementing the division of `x` by `y`. In Pharo,
dividing a `Number` by `0` results in a `ZeroDivide` error. Thus, the following code:

```Smalltalk
(JRPCClient http: 'http://localhost:4000')
callMethod: 'divide' arguments: #(1 0) withId: 1.
callMethod: 'divide' arguments: #(1 0) withId: 1.
```

Will results in a JSON-RPC error for which the error looks like this in JSON format:

```Smalltalk
```json
{
"jsonrpc" : "2.0",
"id" : 1,
"error" : {
"data" : {
"tag" : "",
"errorClass" : "ZeroDivide",
"signalerContext" : "SmallInteger>>/",
"messageText" : "",
"signaler" : "1"
},
"message" : "Internal JSON-RPC error.",
"code" : -32603
}
"jsonrpc" : "2.0",
"id" : 1,
"error" : {
"data" : {
"tag" : "",
"errorClass" : "ZeroDivide",
"signalerContext" : "SmallInteger>>/",
"messageText" : "",
"signaler" : "1"
},
"message" : "Internal JSON-RPC error.",
"code" : -32603
}
}
```

Mind the `data` sub-field inside `error` error field. It contains additional data about the error for which the structure is defined by this particular implementation.
Mind the `data` sub-field inside `error` error field. It contains additional data
about the error for which the structure is defined by this particular implementation.

The structure is the following:
```

```json
{
"errorClass" : String, // The class of the Pharo error.
"signaler" : String, // The object to which the message was sent when the error occured.
"signaler" : String, // The object to which the message was sent when the error occurred.
"signalerContext" : String, // The method in which error was raised formatted as Class>>method
"messageText" : String, // The message the Pharo error hold.
"tag" : String // The tag of the Pharo error.
Expand Down
39 changes: 30 additions & 9 deletions docs/MessageProcessing.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
# Message Processing

JSON RCP messages are processed by instances of `JRPCMessageProcessor` independently of the underlying transport used for receiving and responding the messages.
JSON RCP messages are processed by instances of `JRPCMessageProcessor` independently
of the underlying transport used for receiving and responding the messages.

The message processor has a list of method handlers available that will be searched when a incoming message is received. If a suitable handler is found (the `#methodName` is matching) then it gets executed with the parameters provided in the message.
The message processor has a list of method handlers available that will be
searched when an incoming message is received. If a suitable handler is found
(the `#methodName` is matching) then it gets executed with the parameters provided
in the message.

A message processor can be configured using the following messages:
- `addHandlerNamed:block:`adds a new handler for a method that will evaluate the block provided as argument.
- `addHandlersFromPragmasIn:` searches for `<jrpc>` pragmas declared in the methods of the object provided as argument, and adds a message handler if such pragma is found. When such handler is added, the method in which the pragma was found is sent to the object when a matching JRPC message is received.
- `addHandler:` adds a new handler. Handlers must subclass `JRPCAbstractHandler`, this allows the end user to extend the available options if needed.

The message processor main API is `handleJSON:`, any server implementing a specific transport protocol must obtain the json string and delegate its processing by sending `handleJSON:` to the processor. `handleJSON:` method returns the JSON string to return to the client once the processing is completed.
- `addHandlerNamed:block:` adds a new handler for a method that will evaluate
the block provided as argument.
- `addHandlersFromPragmasIn:` searches for `<jrpc>` pragmas declared in the
methods of the object provided as argument, and adds a message handler if such
pragma is found. When such handler is added, the method in which the pragma was
found is sent to the object when a matching JRPC message is received.
- `addHandler:` adds a new handler. Handlers must subclass `JRPCAbstractHandler`,
this allows the end user to extend the available options if needed.

The message processor main API is `handleJSON:`, any server implementing a specific
transport protocol must obtain the JSON string and delegate its processing by sending
`handleJSON:` to the processor. `handleJSON:` method returns the JSON string to
return to the client once the processing is completed.

## Message handlers

Message handlers are responsible of executing the code related to a JRPC method. All handlers are subclasses of `JRPCAbstractHandler` and need to provide a `methodName` and a way to execute this method with the provided arguments. There's two implementations already available `JRPCBlockHandler` and `JRPCPragmaHandler`.
Message handlers are responsible for executing the code related to a JRPC method.
All handlers are subclasses of `JRPCAbstractHandler` and need to provide a `methodName`
and a way to execute this method with the provided arguments. There are two implementations
already available `JRPCBlockHandler` and `JRPCPragmaHandler`.

- `JRPCBlockHandler` instances are created with a block closure that will be evaluated to compute the method. The parameter names are taken from the block parameters names.
- `JRPCPragmaHandler` instances will search for methods with the `<jrpc>` pragma. Subclasses must define `defaultMethodName` returning the name of the remote method to execute, and the code to be executed is the one in the method including the pragma. The parameter names are taken from the method including the pragma.
- `JRPCBlockHandler` instances are created with a block closure that will be
evaluated to compute the method. The parameter names are taken from the block
parameters names.
- `JRPCPragmaHandler` instances will search for methods with the `<jrpc>` pragma.
Subclasses must define `defaultMethodName` returning the name of the remote method
to execute, and the code to be executed is the one in the method including the
pragma. The parameter names are taken from the method including the pragma.