Direct client
Key takeaways
Direct client | A component that calls a service directly in the same memory space. |
Service | Custom component used to define a method that is called by the direct client. |
References | Component used to store and locate component references. |
DependencyResolver | Component used to resolve component references. |
Introduction
A direct client is a component that calls a service directly in the same memory space. In general, it is used when multiple microservices are deployed in a single container (monolith system) and communication between them can be done by direct calls. Within Pip.Services, the DirectClient component is used to create it.
This tutorial will help you understand how this class works. First, we will see how to create a simple service that contains a method that prints “Hello world”. Then, we will learn how to create a direct client that connects to this service and allows us to use the method previously defined in our service. Finally, we will run our program and see the results.
The service
Our service class is very simple and, for the purpose of this example, has a function named “my_method”, which prints “Hello world”. The following code shows how this class is defined and how to create an instance of it.
import { ConfigParams, IConfigurable, IReferenceable, IReferences } from "pip-services4-components-node";
export async function main() {
// Instantiation
let myService = new MyService();
}
export class MyService implements IConfigurable, IReferenceable {
public configure(config: ConfigParams): void {
}
public setReferences(references: IReferences): void {
}
public myMethod(): void {
console.log('Hello world');
}
}
import (
"context"
"fmt"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
)
func main() {
// Instantiation
myController := &MyService{}
}
type MyService struct {
}
func (c *MyService) Configure(ctx context.Context, config *cconf.ConfigParams) {
}
func (c *MyService) SetReferences(ctx context.Context, references cref.IReferences) {
}
func (c *MyService) MyMethod() {
fmt.Println("Hello world")
}
# Pre-requisites
from pip_services4_components.refer import Descriptor, IReferences, IReferenceable
from pip_services4_components.config import IConfigurable
# Service
class MyService(IConfigurable, IReferenceable):
def __init__(self):
pass
def configure(self, config):
pass
def set_references(self, references: IReferences):
pass
def my_method(self):
print("Hello world")
# Instantiation
myService = MyService()
The direct client
Now that we have our service, we can construct a direct client that communicates with it and calls “my_method”.
To achieve this, we do the following process. First, we create a reference to the service via two components: References and DependencyResolver. This last class is used to give a name to our service’s reference and is added in the init() method. Then, in the setReferences() method, we receive a References object, which is used to associate the client to the service. Lastly, we create a method that invokes “my_method” from the service. Once our class is defined, we create an instance of it. The following code shows how to do this.
import { DependencyResolver, Descriptor, IReferences } from "pip-services4-components-node";
import { DirectClient } from "pip-services4-rpc-node";
// Direct client
export class MyDirectClient extends DirectClient<MyServcie> {
_dependencyResolver = new DependencyResolver();
public constructor() {
super();
this._service = null
this._dependencyResolver.put("service", new Descriptor("pip-services", "service", "*", "*", "1.0"))
}
public setReferences(references: IReferences): void {
this._dependencyResolver.setReferences(references);
this._service = this._dependencyResolver.getOneRequired("service");
}
}
// Instantiation
let client = new MyDirectClient();
import (
"context"
"fmt"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
rpcclnt "github.com/pip-services4/pip-services4-go/pip-services4-rpc-go/clients"
)
// Direct client
type MyDirectClient struct {
*rpcclnt.DirectClient
dependencyResolver *cref.DependencyResolver
service *MyService
}
func NewMyDirectClient() *MyDirectClient {
c := &MyDirectClient{}
c.dependencyResolver = cref.NewDependencyResolver()
c.dependencyResolver.Put(context.Background(), "service", cref.NewDescriptor("pip-services", "service", "*", "*", "1.0"))
return c
}
func (c *MyDirectClient) SetReferences(ctx context.Context, references cref.IReferences) {
c.dependencyResolver.SetReferences(ctx, references)
res, err := c.dependencyResolver.GetOneRequired("service")
if err != nil {
panic(err)
}
c.service = res.(*MyService)
}
func (c *MyDirectClient) MyMethod() {
c.service.MyMethod()
}
// Instantiation
client := NewMyDirectClient();
# Pre-requisites
from pip_services4_rpc.clients import DirectClient
from pip_services4_components.refer import Descriptor, IReferences, DependencyResolver
from pip_services4_components.config import IConfigurable
# Direct client
class MyDirectClient(DirectClient):
_dependencyResolver = DependencyResolver()
def __init__(self):
super(MyDirectClient, self).__init__()
self._service: MyController = None
self._dependencyResolver.put("service", Descriptor("pip-services", "service", "*", "*", "1.0"))
def set_references(self, references: IReferences):
self._dependencyResolver.set_references(references)
self._service = self._dependencyResolver.get_one_required("service")
def my_method(self):
self._service.my_method()
# Instantiation
client = MyDirectClient()
Reference setting
The next step is to define the association between our reference in the client and the service. The following code shows how to do it.
import { Descriptor, References } from "pip-services4-components-node";
// Reference settig
client.setReferences(References.fromTuples(
new Descriptor("pip-services", "service", "service", "default", "1.0"), myService));
// Reference setting
client := NewMyDirectClient()
client.SetReferences(context.Background(), cref.NewReferencesFromTuples(context.Background(),
cref.NewDescriptor("pip-services", "service", "service", "default", "1.0"), myService,
))
# Pre-requisites
from pip_services4_components.refer import References
# Reference setting
client.set_references(References.from_tuples(
Descriptor("pip-services", "service", "service", "default", "1.0"), myService))
Calling “my_method”
Our aim is to call “my_method” from the client. We have made this possible by connecting the service and the client. Thus, our final step is to call this method from the client with the following command:
client.myMethod();
client.MyMethod()
client.my_method()
Which after execution produces the following result:
Final code
The following code summarizes all the previous steps:
import {
ConfigParams, DependencyResolver, Descriptor,
IConfigurable, IReferenceable, IReferences, References
} from "pip-services4-components-node";
import { DirectClient } from "pip-services4-rpc-node";
export async function main() {
// Instantiation
let myService = new MyService();
// Instantiation
let client = new MyDirectClient();
// Reference setting
client.setReferences(References.fromTuples(
new Descriptor("pip-services", "service", "service", "default", "1.0"), myService));
// Calling "my_method"
client.myMethod();
}
export class MyDirectClient extends DirectClient<MyService> {
_dependencyResolver = new DependencyResolver();
public constructor() {
super();
this._service = null
this._dependencyResolver.put("service", new Descriptor("pip-services", "service", "*", "*", "1.0"))
}
public setReferences(references: IReferences): void {
this._dependencyResolver.setReferences(references);
this._service = this._dependencyResolver.getOneRequired("service");
}
public myMethod(): void {
this._service.myMethod();
}
}
export class MyService implements IConfigurable, IReferenceable {
public configure(config: ConfigParams): void {
}
public setReferences(references: IReferences): void {
}
public myMethod(): void {
console.log('Hello world');
}
}
import (
"context"
"fmt"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
rpcclnt "github.com/pip-services4/pip-services4-go/pip-services4-rpc-go/clients"
)
func main() {
// Instantiation
myService := &MyService{}
// Instantiation
client := NewMyDirectClient()
// Reference setting
client.SetReferences(context.Background(), cref.NewReferencesFromTuples(context.Background(),
cref.NewDescriptor("pip-services", "service", "service", "default", "1.0"), myService,
))
// Calling "my_method"
client.MyMethod()
}
// Direct client
type MyDirectClient struct {
*rpcclnt.DirectClient
dependencyResolver *cref.DependencyResolver
service *MyService
}
func NewMyDirectClient() *MyDirectClient {
c := &MyDirectClient{}
c.dependencyResolver = cref.NewDependencyResolver()
c.dependencyResolver.Put(context.Background(), "service", cref.NewDescriptor("pip-services", "service", "*", "*", "1.0"))
return c
}
func (c *MyDirectClient) SetReferences(ctx context.Context, references cref.IReferences) {
c.dependencyResolver.SetReferences(ctx, references)
res, err := c.dependencyResolver.GetOneRequired("service")
if err != nil {
panic(err)
}
c.service = res.(*MyService)
}
func (c *MyDirectClient) MyMethod() {
c.service.MyMethod()
}
type MyService struct {
}
func (c *MyService) Configure(ctx context.Context, config *cconf.ConfigParams) {
}
func (c *MyService) SetReferences(ctx context.Context, references cref.IReferences) {
}
func (c *MyService) MyMethod() {
fmt.Println("Hello world")
}
# Pre-requisites
from pip_services4_rpc.clients import DirectClient
from pip_services4_components.refer import Descriptor, References, IReferences, IReferenceable, DependencyResolver
from pip_services4_components.config import IConfigurable
# Direct client
class MyDirectClient(DirectClient):
_dependencyResolver = DependencyResolver()
def __init__(self):
self._service: MyService = None
self._dependencyResolver.put("service", Descriptor("pip-services", "service", "*", "*", "1.0"))
super(MyDirectClient, self).__init__()
def set_references(self, references: IReferences):
self._dependencyResolver.set_references(references)
self._service = self._dependencyResolver.get_one_required("service")
def my_method(self):
self._service.my_method()
# Instantiation
client = MyDirectClient()
# Controller
class MyService(IConfigurable, IReferenceable):
def __init__(self):
pass
def configure(self, config):
pass
def set_references(self, references: IReferences):
pass
def my_method(self):
print("Hello world")
# Instantiation
myService = MyService()
# Reference setting
client.set_references(References.from_tuples(
Descriptor("pip-services", "service", "service", "default", "1.0"), myService))
# Calling "my_method"
client.my_method()
Which, after running, produces the following outcome:
Wrapping up
In this tutorial, we have seen how to create a direct client by using the DirectClient component. To understand this class, we created a service with a method that prints “Hello world”. Then, we created a client with the service as a dependency and connected both components. Finally, we ran the created method from the client and saw the results.