Is it possible to use two adapters in one project?

Is it possible to include two different adapters inside a project? One should be the default ApplicationAdapter extending JsonApiAdapter And one is for example the SpecialAdapter for REST API calls that are not conform to the JSON API rules (legacy API)? Or is it better to use fetch with JSON.parse to go to legacy API’s?

Yes, you can have many adapters. You’re not required to always extend from one shared application adapter, that is just a default convention.

And how do you “call” or use that second adapter. The first one is this.store.findAll(‘student’); How do I call the second one?

Adapters are “called” per model. So if you have an adapter called “application” it is used as a default and then if you have a model called “student” any requests made re: student resources would use the “student” adapter if it exists and the “application” adapter if not.

Another thing you can (but not necessarily should) do is use store.adapterFor('student') and call methods on the student adapter directly. I’ve seen this used as a way to hold one-off API methods which don’t conform to the “resource” structure but which still are related to a resource (for example a batch attach/detach API endpoint).

Of course the better way might just be to create a service that manages legacy API calls and/or pushes the data into the store.

1 Like

Of course the better way might just be to create a service that manages legacy API calls and/or pushes the data into the store.

That is an interesting idea. What do you mean exactly with this? Create a custom adapter for our legacy API, create a service that act as a layer? What do you mean exactly with “pushes the data to the store”? JSON.serialize to the models? Or?

Well I should back up a little bit first. The best solution kinda depends on your APIs and use case.

If you are transitioning legacy => JSON-API roughly by “resource” e.g. by model type, and if your legacy API is fairly “resource oriented” it would make sense to have two base adapters (application, which extends JSONAPI adapter, and legacy, which extends Rest or JSON adapter). Then any models that still use legacy APIs have model-specific adapters which extend the legacy adapter, and you delete those model specific adapters when you want to convert to the JSON API endpoints. You’d probably want a legacy serializer to pair with the adapter in this case, so you’d need per-model serializers for any resource that depends on the legacy API as well. The advantage here is that A) ember data is still doing most of the work and B) the per-model adapter/serializers could be further customized to fit any stage of transition or idiomatic inconsistency per-resource.

If your legacy API doesn’t map to “resources” so nicely, or if you’re using a different strategy to rewrite it, BUT the legacy API resources you need are still resource-specific and somewhat conventional, it might make sense to add methods on the adapter and call then using adapterFor. The advantage is that you get some of the adapter stuff like buildURL to make it a little easier. This really only makes sense though if the legacy endpoints you want to hit match up to a model (e.g. you have an endpoint that relates to a user model, but doesn’t fit the ember data conventions.

If the above situations don’t really apply, a service is probably your best bet. In this case you wouldn’t use an adapter at all. You’d just have service methods (probably async methods or use ember concurrency tasks or something) that make requests to the legacy API and (optionally, if it makes sense) serialize the data and push it into the store using store.pushPayload.

You probably want to go with the first option because it sounds like your legacy API is still ember-data friendly(?). I’d only consider the other two options if the legacy API is very weird.

1 Like