Spring Data Rest 2.4 doesn't work with {?page,size,sort} links - spring-data-rest

I've faced with the following problem:
Spring Data Rest version: org.springframework.data:spring-data-rest-webmvc:2.4.0.RELEASE
When i perform the query: http://localhost:8080/data/entities/ - the base query for my Rest servlet.
It produces the links for all entities i have. The links has the following standard form:
"entityA": {
"href": "http://localhost:8080/data/entities/entitiA{?page,size,sort}",
"templated": true
}
When i try to perform the generated link:
http://localhost:8080/data/entities/entitiA{?page,size,sort}
I have 404 NotFound exception.
But when i execute
http://localhost:8080/data/entities/entitiA
it works fine.
Do you have any ideas about it or could you suggest any solution to execute links in the format:
http://localhost:8080/data/entities/entitiA{?page,size,sort}
Thanks!

Sometimes it is worth to look at the documentation ;-)
http://docs.spring.io/spring-data/rest/docs/2.4.0.RELEASE/reference/html/#paging-and-sorting
{?page,size,sort} is a template. It tells you which request parameters the resource supports. You are not supposed to use a templated link as it is in the response - you expand it first.
So a request like this should be working
http://localhost:8080/cars/data/entities/entitiA?page=1&size=20

Related

Recommended dynamic runtime configuration technique on nuxtjs (other than dotenv)

I have been trying to use publicRuntimeConfig / privateRuntimeConfig
On nuxt 2.4.1, I have defined my runtime config as follows on nuxt.config.js
publicRuntimeConfig: {
DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL,
},
privateRuntimeConfig: {
AUTH_APP_CLIENT_SECRET: process.env.VUE_APP_AUTH_APP_CLIENT_SECRET,
},
and calling it as follows on my login.vue
asyncData( ctx ) {
console.log(ctx.$config.DATA_API_HOST_URL)
//some activity
}
The keys are showing up on $config inside asyncData. I debugged on chrome dev tools. But value is not read from process.env.VUE_APP_DATA_API_HOST_URL. The value is showing up as undefined. However, process.env.VUE_APP_DATA_API_HOST_URL is showing the value OK. The whole point is to move away from process.env.
this.$config.DATA_API_HOST_URL also does not access the values.
'${DATA_API_HOST_URL}' is shown in examples but I believe it is only for explicit param declarations at asyncData like asyncData( { $config : {DATA_API_HOST_URL}).
When I pass values as it is using DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL || 'https://test.api.com', it seems to copy the value fine using ctx.$config.DATA_API_HOST_URL!
Looking to me like copying process.env to *RuntimeConfig has a problem!
What is the recommended way of importing and using runtime configurations?
As per documentation in the Nuxt blog post you marked, the feature your are trying to use is released in 2.13 (you´re using 2.4 if i not misunderstood). That could be the reason behind the behaviour you're seeing.
I'd recommend update your project dependencies or trying another approach.
I think you should use Docker to set dynamic runtime config like link below:
https://dev.to/frontendfoxes/dockerise-your-nuxt-ssr-app-like-a-boss-a-true-vue-vixens-story-4mm6

How to build Query Parameter using Spring Traverson

I have a Spring Data Rest webservice with QueryDSL Web Support enabled so I can query any of the fields directly like below;
http://localhost:9000/api/prod1007?cinfo1=0126486035
And I was using Traverson to access this service but traverson is not generating the query parameter as above; below is my code (I have tried both withTemplateParameters() and withParameters() in Hop level)
Code:
Map<String,Object> parameters = new HashMap<String,Object>();
parameters.put("cinfo1", "0127498374");
PagedResources<Tbpinstance> items = traverson
.follow(Hop.rel("prod1007"))
.withTemplateParameters(parameters)
.toObject(resourceParameterizedTypeReference);
Any Help is much appreciated. Thanks!
Traverson needs to know where to put those parameters. They could be path parameters, or they could be query parameters. Furthermore, Traverson navigates the service from the root, so the parameters might need to be inserted somewhere in the middle, and not in the final step only.
For these reasons the server needs to clearly tell how to use the parameters. Traverson needs a HATEOAS-"directory" for the service. When Traverson HTTP GETs the http://localhost:9000/api document, it needs to contain a link similar to this:
"_links" : {
"product" : {
"href" : "http://localhost:9000/api/prod1007{?cinfo1}",
"templated" : true
},
}
Now it knows that the cinfo1 parameter is a query parameter and will be able to put it into its place.
#ZeroOne, you are entirely correct, that is what the response from the server should look like. Currently spring-hateoas does not support responses that look like that (I expect it will in the future as I have seen comments by Oliver Gierke indicating that spring-hateoas is going through a major upgrade).
As at the time of writing, to generate responses from the server as you describe, we have used spring-hateoas-ext mentioned in https://github.com/spring-projects/spring-hateoas/issues/169. You can find code at https://github.com/dschulten/hydra-java#affordancebuilder-for-rich-hyperlinks-from-v-0-2-0.
This is a 'drop in replacement' for spring-hateoas' ControllerLinkBuilder.
Here is the maven dependency we use (but check for the latest version).
<!-- Drop in replacement from spring-hateoas ControllerLinkBuilder -->
<dependency>
<groupId>de.escalon.hypermedia</groupId>
<artifactId>spring-hateoas-ext</artifactId>
<version>0.3.0-beta6</version>
</dependency>
Here's the import we use in our ResourceAssemblers.
import static de.escalon.hypermedia.spring.AffordanceBuilder.*;

Magento SOAP API: Error in retrieving catalogCategoryTree

Currently I'm using Magento 1.9.01 and PHP 5.3.28. In ASP .NET I'm trying to retrieve the catalog tree by using the SOAP API using the following code:
var magentoService = new MagentoService.Mage_Api_Model_Server_Wsi_HandlerPortTypeClient();
var sessionId = magentoService.login(userName, apiKey);
var categoryTree = magentoService.catalogCategoryTree(sessionId, "", "");
The errror I get is "Internal Error. Please see log for details."
And in the logs I can see the following:
Argument 1 passed to Mage_Catalog_Model_Category_Api::_nodeToArray() must be an instance of Varien_Data_Tree_Node, null given
From what I've read it can be a bug with PHP 5.4 or greater, but not the version I'm using... So if someone has any idea how to solve this, it will be greatly appreaciated.
Seems pretty straight forward, though the error thrown suggests a much bigger problem. First make sure that the variables are exactly as you specified in your Magento installation (pay attention to caps). Second you can't pass empty strings, instead try "Null".
Good luck

JayData oData request with custom headers - ROUND 2

Few month back I was working on some Odata WCF project and I had some problems with parsing custom headers for token auth (apiKey).
At that time, being quite a noob (still am!), I posted this SO question: JayData oData request with custom headers
Today I am working on a new project with Jaydata Odata server and client library and this:
application.context.prepareRequest = function (r) {
r[0].headers['apikey'] = '123456';
};
was working fine till I had to do a MERGE request. I found out that somehow MERGE request was overriding my headers so I investigated further.
It appears at first that in the oDataProvider.js (~line 617) in the _saveRest method the headers are not inherited:
request = {
requestUri: this.providerConfiguration.oDataServiceHost + '/',
headers: {
MaxDataServiceVersion: this.providerConfiguration.maxDataServiceVersion
}
};
but a few lines later we get:
this.context.prepareRequest.call(this, requestData);
which "should" call my own prepareRequest, but doesnt... Instead it still points to:
//Line 11302 jaydata.js
prepareRequest: function () { },
which of course does... nothing! Funnilly enough, when you execute a simple GET the same code supposedly on the same context instance works and points to my prepareRequest override.
I can assert with enough confidence that somehow the context between GET/MERGE is not the same instance. I cant see, however, any place where the context instance is reassigned.
Has anyone got a clue?
PS: this is NOT a CORS issue. My OPTIONS is passing fine and manually feeding the headers in oDataProvider works.
More
I followed the lead on different context instances and found something interesting. calling EntitySet.save() ends up calling the EntityContext constructor. see trace:
$data.Class.define.constructor (jaydata.js:10015)
EntityContext (VM110762:7)
Service (VM110840:8)
storeToken.factory (jaydata.js:14166)
$data.Class.define._getContextPromise (jaydata.js:13725)
$data.Class.define._getStoreContext (jaydata.js:13700)
$data.Class.define._getStoreEntitySet (jaydata.js:13756)
$data.Class.define.EntityInstanceSave (jaydata.js:13837)
$data.Entity.$data.Class.define.save (jaydata.js:9774)
(anonymous function) (app.js:162) // My save()
That explains why I get two different instances...
Hack
Replacing the prepareRequest function direcly in the class definition works, but its ugly!
for now I can cope with this:
$data.EntityContext.prototype.prepareRequest = function (r) {
r[0].headers['apikey'] = '12345';
};
This works fine as long as you only need to talk to a single endpoint.
Final word based on my experience
As much as I like JayData, it is obvious that they created a monster and its getting out of their hands (poor forum, no community, half-documented,...).
I chose JD because I was lazy and wanted to keep working with my old WCF DataService. Switching to Web API seemed wrong or too much work for me.
Also as a .net dev I liked strong typing of my entities and the ability to work with a concrete model generated from the JD tools. However, in the end, I was adding confusion. Every time my server side model changed I had to fetch the new metadata and scaffold a new entityModel.
I ended up by switching to Web Api and migrated my data service layer to Breeze. And seriously! its a breeze to work with it!
The documentation is absolutely brilliant and here on S.O you can always count on Ward or Jay Tarband to reply with a very high amount of professionalism.
In the end I realize this should probably be more a wiki than a Question.....

Backbone using GET instead of PUT or POST

I'm having some issues with a Backbone project that I am working on.
I have the following model:
class App.Models.Purchaseorder extends Backbone.Model
url: ->
base = 'api/purchaseorders'
if this.isNew()
base
else
base + '/' + this.id;
urlRoot: 'api/purchaseorders'
When I run the following in the console:
po = new App.Models.Purchaseorders;
po.set({'po_number': '1234', 'locale': 'Home', 'po_date': '3/22/2012'});
it appears to set the attributes correctly. However, if I run
po.save()
I would expect it to do a POST request to the api/purchaseorders URL. When I debug through the save() and sync() functions in the Backbone JS, it looks like it is indeed running a POST, but at the last minute, it looks as if it is really doing a GET http://i.imgur.com/dQK88.png
I am a little confused as to why this would be happening. I am having similar issues when trying to do an update -- which should be doing a PUT. I am assuming something is funky in the model, but I have no clue what it could be.
Any help would be greatly appreciated.
Thanks!
I tested the code you have in the question (had to call new App.Models.Purchaseorder, without the s, though FYI) and it does a POST as expected.
What version of Backbone and Underscore are you using?
Here's a fiddle.