Spring Data Rest Neo4j: Template must not be null or empty - neo4j

I am creating what I believe to be a fairly simple domain model in Spring.
#NodeEntity
class Dependency {
#GraphId
private Long id
String groupId
String artifactId
String version
#Fetch
#RelatedTo(type = "DEPENDS_ON", direction = OUTGOING)
Set<Dependency> dependencies = new HashSet<Dependency>()
}
note* the above is written in groovy.
I have also created a subsequent Repository (all textbook so far!).
#RepositoryRestResource(collectionResourceRel = "dependency", path = "dependency")
interface DependencyRepository extends PagingAndSortingRepository<Dependency, Long> {
List<Dependency> findByArtifactId(#Param("artifactId") String artifactId)
}
And finally the application class....
#EnableNeo4jRepositories(basePackages = "io.byteshifter.depsgraph")
#SpringBootApplication
class Application extends Neo4jConfiguration {
public Application() {
setBasePackage("io.byteshifter.depsgraph")
}
#Bean(destroyMethod = "shutdown")
GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("target/dependency.db")
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application, args)
}
}
Now I would expect when I fire the following payload at http://127.0.0.1:8080/dependency that it would create all the objects and relationships..
{
"groupId": "group1",
"artifactId": "artifact1",
"version": "1.0",
"dependencies" : [
{"groupId": "group2", "artifactId": "artifact2", "version": "2.0"},
{"groupId": "group3", "artifactId": "artifact3", "version": "3.0"}
]
}
Instead, I get..
{
"cause": {
"cause": {
"cause": null,
"message": "Template must not be null or empty!"
},
"message": "Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0])"
},
"message": "Could not read JSON: Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0])"
}
I have no doubt this is a lack of understanding on my behalf. If anyone could help steer me in the right direction that would be very welcomed.

My REST knowledge has failed me. I should have been using a URI to represent other dependencies. See below:
{
"groupId": "group3",
"artifactId": "artifact3",
"version": "1.0",
"dependencies": ["http://127.0.0.1:8080/dependency/0", "http://127.0.0.1:8080/dependency/1", "http://127.0.0.1:8080/dependency/2"]
}

Related

index percolate queries using spring data jpa

Here is my Dto for percolator query class.
#Data
#Document(indexName = "#{#es.indexName}")
#Builder(builderClassName = "RuleBuilder")
public class Rule {
#Id
private String id = UUID.randomUUID().toString();
private QueryBuilder query;
private RuleDataDto data;
public static class RuleBuilder {
private String id = UUID.randomUUID().toString();
}
}
Index Mapping
{
"mappings": {
"properties": {
"query": {
"type": "percolator"
},
"data": {
"properties": {
"subType": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"content": {
"type": "text"
}
}
}
}
based on criteria I am generating queries and trying to index those to percolator. but getting below exception
query malformed, no start_object after query name
what should be the query field Type? can someone help me on this
You are trying to store an Elasticsearch object (QueryBuilder) in Elasticsearch without specifying the mapping type.
You will need to annotate your query property as percolator type and might change the type of your property to a String:
#Document(indexName = "#{#es.indexName}")
public class Rule {
#Id
private String _id;
#Field(type = FieldType.Percolator)
private String query;
// ...
}
Or, if you want to have some other class for the query property you'll need a custom converter that will convert your object into a valid JSON query - see the documentation for the percolator mapping.

Swagger shows extra parameters in request body

We are using springfox-swagger-ui and springfox-swagger2 of version 2.7.0.
A post api has the following signature :
#ApiOperation("Edits information about employees")
#PostMapping(path = "/employee/edit", headers = EndPoints.VERSION_1)
#ApiResponses(value = {
#ApiResponse(code = 409, message = "Data mismatch"),
#ApiResponse(code = 400, message = "Invalid data passed")
})
public ResponseEntity<Employee> manageEmployee(
#RequestHeader("employeeId") final String iEmployeeId,
#RequestBody(required = true) #Valid final Employee iEmployee)
The object employee is:
public class Employee implements Serializable {
private static final long serialVersionUID = -7315844547195801413L;
private String employeeName;
private Long employeeId;
private #Valid #NotNull List<Address> addresses;
// getter and setter methods
#Validated
public static class Address implements Serializable {
private static final long serialVersionUID = 6748945632164495934L;
private String addressId;
#ValidAddress
private String addressName;
//getter and setter methods
}
}
But the swagger shows the request body as :
{
"addresses": {
"addressId": "string",
"addressName": "string",
"permanentAddress": [
{
"addressId": "string",
"addressName": "string"
}
]
},
"employeeName": "string",
"employeeId": 0
}
The object permanentAddress is not present in my code.
How can this be resolved?
Before questioning why permantnAddress, I think it's more important to find out why addresses is an object of addressId, addressName, and a list of Address. Something doesn't look right in the JSON.
The Employee object looks like:
{
addresses: [
addressId: "string",
addressName: "string"
],
employeeName: "string",
employeeId: 0
}
permanentAddress is the correct object for List addresses

Adding x-logo vendor extension using Swashbuckle Asp.Net Core for ReDoc

I'm using swagger.json file (generated by Swashbuckle) for ReDoc to display API documentation.
What I Need:
Add x-logo vendor extension to swagger json generated using Swashbuckle (Swashbuckle.AspNetCore.SwaggerGen library) so that ReDoc UI shows logo at the top left corner like this
Problem:
I was able to add x-log to the swagger.json file but it is added to wrong section of the file. It needs to be inside info section.
This is what I have done to add the x-logo
Created a document filter like below
public class XLogoDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Extensions["x-logo"] = new { url = "https://URL/of/the/logo", altText = "Company Logo" };
}
}
Added the filter to SwaggerDoc as
services.AddSwaggerGen(options =>
{
options.DocumentFilter<XLogoDocumentFilter>();
});
Actual
{
"swagger": "2.0",
"info": {
"version": "v1",
"title":"Sample REST API"
},
"x-logo": {
"url": "https://rebilly.github.io/ReDoc/petstore-logo.png",
"altText": "Aimia Logo"
}
}
Expected
{
"swagger": "2.0",
"info": {
"version": "v1",
"title":"Sample REST API",
"x-logo": {
"url": "https://rebilly.github.io/ReDoc/petstore-logo.png",
"altText": "Aimia Logo"
}
},
}
Really appreciate any help or suggestions to have the x-logo in the correct section of the swagger.json file.
After typing the question I found the solution myself. Instead of adding extension directly to swaggerDoc, add it to swaggerDoc.Info object.
public class XLogoDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
// need to check if extension already exists, otherwise swagger
// tries to re-add it and results in error
if (!swaggerDoc.Info.Extensions.ContainsKey("x-logo"))
{
swaggerDoc.Info.Extensions.Add("x-logo", new {
url = "https://URL/To/The/Logo",
altText = "Logo",
});
}
}
}
The newer versions of Swashbuckle support this in the SwaggerDoc setup:
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = ApiDescription,
Version = "v1",
Extensions = new Dictionary<string, IOpenApiExtension>
{
{"x-logo", new OpenApiObject
{
{"url", new OpenApiString("https://blah.com/logo")},
{ "altText", new OpenApiString("The Logo")}
}
}
}
});
for .NET core 2.2 and higher
public class XLogoDocumentFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
// need to check if extension already exists, otherwise swagger
// tries to re-add it and results in error
if (!swaggerDoc.Info.Extensions.ContainsKey("x-logo"))
swaggerDoc.Info.Extensions.Add("x-logo", new OpenApiObject
{
{"url", new OpenApiString("https://www.petstore.com/assets/images/logo.png")},
{"backgroundColor", new OpenApiString("#FFFFFF")},
{"altText", new OpenApiString("PetStore Logo")}
});
}
}

Neo4j 3.0.6 and neo4j-ogm 2.0.5 - Create duplicate data on database

I have a problem with neo4j database. When I try to init data, it should be just create one sample data but sometimes when I try to init data, it create double sample data. There is no trace about calling second times. This is the Config of my Neo4j
#Configuration
#EnableNeo4jRepositories(basePackages = "com.example.neo.repository")
#EnableTransactionManagement
public class Neo4jConfig extends Neo4jConfiguration {
#Override
#Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory("com.example.neo.model", "BOOT-INF.classes.com.example.neo.model");
}
// needed for session in view in web-applications
#Override
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}
This is how I called my function
#RequestMapping(value = "/initCurrency")
public ModelAndView initCurrency() {
initializationService.initCurrency();
ModelAndView model = new ModelAndView("redirect:/");
return model;
}
This is the initializationService function
private String[][] currencyList = {
{ "USD", "7.5" },
{ "DKK", "1" },
{ "AFN", "1"},{ "EUR", "1"},{ "ALL", "1"},{ "DZD", "1"},{ "USD", "1"},{ "AOA", "1"},{ "XCD", "1"},
{ "ARS", "1"},{ "AMD", "1"},{ "AWG", "1"},{ "SHP", "1"},{ "AUD", "1"},{ "AZN", "1"},{ "BSD", "1"},
{ "BHD", "1"},{ "BDT", "1"},{ "BBD", "1"}
}
#Override
public void initCurrency() {
for (String[] currency : currencyList) {
Currency existCurrency = currencyService.findByName(currency[0]);
if (existCurrency == null) {
existCurrency = new Currency(currency[0], Double.valueOf(currency[1]));
currencyService.save(existCurrency);
}
}
}
The only reliable way to avoid duplicates is to have an actual unicity constraint on the property:
CREATE CONSTRAINT ON (n:Currency) ASSERT n.name IS UNIQUE;
There's no way in SDN 4.[0-2] (yet) to create such a constraint from the model (there was in SDN 3.x with the #Indexed or #Indexed(unique = true) annotation), so you'll have to run the query independently (for example using Liquigraph!).
Doing a lookup to guard the creation is not enough in a concurrent environment (sequential calls are OK), because there's no lock between the read and the write, which can result in the following scenario with an interleaved execution:
Thread A checks the existence, doesn't find a node
Thread B checks the existence, doesn't find a node either
Thread A creates a currency node named "USB"
Thread B creates another currency node with the same name
Since you end up with duplicates, 2 concurrent calls are happening. A load balancer with a really short timeout and configured to retry? Activate HTTP logs, add some logging in the Spring controller or service, capture the traffic with tcpdump, etc. It will be easier to isolate the second call once the unicity constraint is active, since you'll get an exception.

APIs not getting detected by swagger on a Spring ROO project

I have tried a lot of things but APIs are not getting detected by swagger for some reason. Do i have to specify a package for swagger to scan? or some url include patterns?
My Swager Config :
#Configuration
#EnableSwagger
#EnableWebMvc
public class SwaggerConfiguration {
private final Logger log = LoggerFactory
.getLogger(SwaggerConfiguration.class);
/**
* Swagger Spring MVC configuration.
*/
#Bean
public SwaggerSpringMvcPlugin swaggerSpringMvcPlugin(
SpringSwaggerConfig springSwaggerConfig) {
log.debug("Starting Swagger");
StopWatch watch = new StopWatch();
watch.start();
SwaggerSpringMvcPlugin swaggerSpringMvcPlugin = new SwaggerSpringMvcPlugin(
springSwaggerConfig).apiInfo(apiInfo())
.genericModelSubstitutes(ResponseEntity.class);
swaggerSpringMvcPlugin.build();
watch.stop();
log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
return swaggerSpringMvcPlugin;
}
/**
* API Info as it appears on the swagger-ui page.
*/
private ApiInfo apiInfo() {
return new ApiInfo("Title", "Description", "terms of service",
"contact", "license", "licenseUrl");
}
}
Sample Controller
#RequestMapping("/settings")
#Controller
#Api(value = "/settings", description = "Endpoint for settings management")
public class SettingsController {
#ApiOperation(value = "API Operation")
#RequestMapping(value = "/changepassword", method = RequestMethod.POST)
public #ResponseBody Map<String, Object> changePassword(#RequestParam Map<String, String> userProperties,
Model model, HttpServletRequest httpServletRequest, Locale locale) {
Map<String, Object> responseMap = new HashMap<String, Object>();
return responseMap;
}
}
I get an empty response
{
"apiVersion": "1.0",
"swaggerVersion": "1.2",
"apis": [ ],
"authorizations": [ ],
"info":
{
"title": "Title",
"description": "Description",
"termsOfServiceUrl": "terms of service",
"contact": "contact",
"license": "license",
"licenseUrl": "licenseUrl"
}
}
I am using swagger-springmvc version 1.0.2 and spring version 4.1.6.RELEASE
Follow the instructions in the following URL :
http://naddame.blogspot.in/2014/12/spring-roo-mvc-integration-for-swagger.html

Resources