Inject rest router in controller - loopback

I need a route who return all my API routes in an array.
I'm trying to inject rest router to use the method "list" but I get this error:
The key 'rest.router' is not bound to any value in context RequestContext-y_3kWzd3Ra-inz75ketkRw-5 (context: RequestContext-y_3kWzd3Ra-inz75ketkRw-5, binding: rest.router, resolutionPath: controllers.DiscoveryController --> #DiscoveryController.constructor[0])
My code :
export class DiscoveryController {
constructor(#inject(RestBindings.ROUTER) private readonly router: RestRouter) {}
#get('/discovery')
#response(200)
discovery(): [] {
console.log(this.router.list());
return [];
}
}
Does anyone know how to inject router to get all routes or if another method exists ?
Thanks

There's file named openapi-spec.ts in your loopback4 application.
In that file, there will be a line:
const outFile = process.argv[2] ?? '';
Change it to:
const outFile = process.argv[2] ?? './openapi.json';
Then do "npm run openapi-spec".
This will create a file named openapi.json in your root directory, it has all the details of your existing APIs.
If you want do this at runtime, then add this to your "prestart" script.

Related

How to create a custom class in NestJS and work with the instance of the class

I'm trying to create a helper class in NestJS which i can use in every file.
I tried to create the following class:
export class Logging {
public status: string;
private currentLog: Model<LogDocument>;
constructor(#InjectModel(Log.name) readonly log?: Model<LogDocument>) {
// Create a new log item when new instance of class is created
this.currentLog = new this.log({
title: 'New Log',
status: SyncStatusType.IN_PROGRESS,
startTime: new Date(),
});
}
public addCrashLog() {
// Update current log
}
public addSuccessLog() {
// Update current log
}
public finish() {
// Set status and update log
}
}
I want to be able to use this class in every other file and create a new instance of the class if necessary.
const newLog = new Logging();
newLog.addCrashLog();
....
Does someone have an idea how I can archive that with NestJS? Because I'm always having problems with dependency injection in NestJS when I'm trying to create a custom class.
First off, don't add the Logging class to any providers array, as that's what will tell Nest to create the instance. Next, if you're passing the values yourself, you don't need the #InjectModel() there's no need, as you're creating the class yourself. Lastly, just use the class as your example already shows, using the new keyword and handling the instantiation yourself. That should be all there is to it

Finatra: How can I inject a property value to the controller?

I want to do something like that
class AssetsController #Inject()(path: String) extends Controller {
// ...
}
The path should be taken from application.conf where the key is path.to.something. In the future, I may add some other properties (source is the same *.conf file) to my controller.
Is it possible to that in Finatra?
PS
When using Spring Framework you can inject a value in this way
#Value("#{configuration.key}")
private String key;
Maybe in Finatra there is something similar to String approach?
Finatra doesn't read configuration from files. You have to pass the config via command line options and can get the options via #Flag annotation. For example,
$ java -jar app.jar -path=/foo/bar
// MyController.scala
class MyController #Inject(#Flag("path") path: String) {
def index(request: Request) = {
path // "/foo/bar"
}
}
You can read the doc for more info.

Using my own service with Laravel4

In my app, I was testing Google Directions API with ajax, but since I was just testing all the logic was in the routes.php file. Now I want to do things the proper way and have three layers: route, controller and service.
So in the routes I tell Laravel which method should be executed:
Route::get('/search', 'DirectionsAPIController#search');
And the method just returns what the service is supposed to return:
class DirectionsAPIController extends BaseController {
public function search() {
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
I created the service in app/libraries/Services/Directions and called it DirectionsSearchService.php and copied all the logic I developed in routes:
class DirectionsSearchService {
public function search($input = array()) {
$origin = $input['origin'];
$destination = $input['destination'];
$mode = $input['mode'];
// do stuf...
return $data;
}
}
I read the docs and some place else (and this too) and did what I was supposed to do to register a service:
class DirectionsAPIController extends BaseController {
public function search() {
App::register('libraries\Services\Directions\DirectionsSearchService');
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
// app/libraries/Services/Directions/DirectionsSearchService.php
use Illuminate\Support\ServiceProvider;
class DirectionsSearchService extends ServiceProvider {
}
I also tried adding libraries\Services\Directions\DirectionsSearchService to the providers array in app/config/app.php.
However, I am getting this error:
HP Fatal error: Class
'libraries\Services\Directions\DirectionsSearchService' not found in
/home/user/www/my-app-laravel/bootstrap/compiled.php on line 549
What am I doing wrong? And what is the usual way to use your own services? I don't want to place all the logic in the controller...
2 main things that you are missing:
There is a difference between a ServiceProvider and your class. A service provider in Laravel tells Laravel where to go look for the service, but it does not contain the service logic itself. So DirectionsSearchService should not be both, imho.
You need to register your classes with composer.json so that autoloader knows that your class exists.
To keep it simple I'll go with Laravel IoC's automatic resolution and not using a service provider for now.
app/libraries/Services/Directions/DirectionsSearchService.php:
namespace Services\Directions;
class DirectionsSearchService
{
public function search($input = array())
{
// Your search logic
}
}
You might notice that DirectionsSearchService does not extend anything. Your service becomes very loosely coupled.
And in your DirectionsAPIController.php you do:
class DirectionsAPIController extends BaseController
{
protected $directionsSearchService;
public function __construct(Services\Directions\DirectionsSearchService $directionsSearchService)
{
$this->directionsSearchService = $directionsSearchService;
}
public function search()
{
return $this->directionsSearchService->search(Input::all());
}
}
With the code above, when Laravel tries to __construct() your controller, it will look for Services\Directions\DirectionsSearchService and injects into the controller for you automatically. In the constructor, we simply need to set it to an instance variable so your search() can use it when needed.
The second thing that you are missing is to register your classes with composer's autoload. Do this by adding to composer.json's autoload section:
"autoload": {
"classmap": [
... // Laravel's default classmap autoloads
],
"psr-4": {
"Services\\": "app/libraries/Services"
}
}
And do a composer dump-autoload after making changes to composer.json. And your code should be working again.
The suggestion above can also be better with a service provider and coding to the interface. It would make it easier to control what to inject into your controller, and hence easier to create and inject in a mock for testing.
It involves quite a few more steps so I won't mention that here, but you can read more in Exploring Laravel’s IoC container and Laravel 4 Controller Testing.

Error in using my own Curl class in laravel

i have laravel 4 installed in my wamp server. this what i did :
1-add this "app/classes" to composer.json.
2-create folder classes in app and put Curl.php class in that folder.
3-add this app_path().'/classes', to global.php inside app/start.
4-run composer dump-autoload in command in www directory.
5-for using like Curl::help() must add this alias to app/config/app.php aliases section 'Curl'=>'Curl' .
after doing this when i return return Curl::hello(); in router this page comes :
http://www.mediafire.com/view/h9489jr5s2699ty/err.PNG
my Curl's class : Curl class
any help??
This is not how Laravel aliases works, you need more code (create Facades and Service Providers) to make it work.
So you have some options:
1) Remove the Alias from app/config/app.php and instantiate your class:
$curl = new Curl;
$curl->help();
2) Instantiate your class and bind it to the IoC container, in global.php, filters.php or create a file for that:
App::bindShared('mycurl', function($app)
{
return new Curl;
});
And create a Facade:
<?php namespace MyClasses\Facades;
use Illuminate\Support\Facades\Facade;
class MyCurlFacade extends Facade {
protected static function getFacadeAccessor()
{
return 'mycurl';
}
}
Your Alias has to point to this Facade script file, like all the others you see in app.php.
'Curl' => 'MyClasses\MyCurlFacade',
And it should work like this Curl::hello();.
3) Create the usual (correct?) Laravel structure, which also includes a ServiceProvider to instantiate your class and bind it to the IoC container in the application Boot:
<?php namespace MyClasses;
use Illuminate\Support\ServiceProvider;
class MyCurlServiceProvider extends ServiceProvider {
protected $defer = false;
public function boot()
{
}
public function register()
{
{
$this->app['mycurl'] = $this->app->share(function($app)
{
return new MyCurl;
});
}
public function provides()
{
return array('mycurl');
}
}
THIS IS UNTESTED CODE, SO DO NOT EXPECT IT TO WORK IN THE FIRST RUN

How to resolve with a default class if a matching register is not found in Autofac

I am using the following code for register:
builder.RegisterType<QCatVCardParser>().Named<IQCatParser>(".VCF");
builder.RegisterType<QCatVCardParser>().Named<IQCatParser>(".VCARD");
builder.RegisterType<QCatOutlookMessageParser>().Named<IQCatParser>(".MSG");
builder.RegisterType<QCatMimeMessageParser>().Named<IQCatParser>(".EML");
builder.RegisterType<QCatCalendarParser>().Named<IQCatParser>(".ICS");
container = builder.Build();
To retrieve a class reference I am using the below code:
var r = container
.ResolveNamed<IQCatParser>(Path.GetExtension(fileName).ToUpperInvariant());
Now my question is if a unsuppoted file extension comes let's say .DOC I want to resolve it with a component among one of the registered classes or else with the first registered class.
Is it possible to do this with AutoFac?
You can do this with Autofac. You need to create an IRegistrationSource that can provide the default registration if needed. For example, here is the RegistrationsFor code of a source that provides settings classes:
var typedService = service as IServiceWithType;
if (typedService != null && typedService.ServiceType.IsClass && typeof(ISettings).IsAssignableFrom(typedService.ServiceType))
{
yield return RegistrationBuilder.ForDelegate((c, p) => c.Resolve<ISettingsReader>().Load(typedService.ServiceType))
.As(typedService.ServiceType)
.CreateRegistration();
}
Then, inside of a module or directly using your Autofac builder, call RegisterSource to hook up the new registration source.