Xtend's _field naming and SpringData's repository naming conventions - java

It seems that the naming conventions between Xtend and Spring Data are incompatible.
For example:
// User.xtend
class User {
#Property
var Long id;
}
interface UserRepository extends JpaRepository<User> {
public User findById(Long id)
}
The #Property annotation renames id to _id, which causes Spring Data to fail, claiming No property id found
Is there a way to either:
Suppress Xtend's renaming of the field
"Teach" Spring Data about the naming convention (Looking for a field? Add an underscore)
Instruct Spring Data to use property-access, rather than field-access for the property resolution?
Any of these would solve this issue, I believe.

Since 2.7.3 the #Property annotation has been superceded by #Accessors, which no longer prepends the fields with an underscore.
Before 2.7.3 you have to build your own #Property annotation which doesn't prepend an underscore to the field's name.
See http://www.eclipse.org/xtend/documentation.html#activeAnnotations
(updated)

Related

How to make graphql-java-annotations recognize the getters methods as fieldname (without the get)

I'm in the process of migrating graphql-java-annotations library from version 0.13 to current 6.1 version.
In our application there are many java interfaces which define getter methods for fields.
In version 0.13 we have those getters annotated with #GraphQLField and then used with the field name in GraphQL Queries.
For example:
#GraphQLField
String getName();
It would be referenced as name in GraphQL Queries.
In the current version, the getter method is no longer recognized, and we need to manually annotate the each field with #GraphQLName to add name to the GraphQL schema.
In the previous example the following change would work:
#GraphQLField
#GraphQLName("name")
String getName();
Is there any way to prevent changing all the getters in interfaces by adding the #GraphQLName annotation? Do you know why the getters methods are no longer recognized?
Just for reference, we were able to solve the problem with the following line:
GraphQLAnnotations.getInstance()
.getObjectHandler()
.getTypeRetriever()
.getGraphQLFieldRetriever()
.setAlwaysPrettify(true);

How to make Spring Data JPA by default naming from camelCase to snake_case unless explicitly specified?

By default, my Spring Boot project had JPA mapping entity properties to table columns by transforming the names from camelCase to snake_case (e.g. from fooBar to foo_bar).
I'm working on an existing DB, where the entity property names were kept as is for the table column names (e.g. from fooBar to fooBar), so I tried to use the #Column annotation to explicitly specify the name:
#Column(name = "fooBar")
private String fooBar;
This wasn't working. I followed the advice given here:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
My #Column is now successfully taken into account, but I'm losing the camelCase to snake_case implicit transformation on the properties that don't have the #Column the annotation.
Any idea how to transform from camelCase to snake_case by default, unless explicitly specified in the #Column annotation?
Somehow the default JPA behavior of converting to snake case was not working when I injected my custom spring datasource beans for my H2 and postgres repositories. I wanted to convert camel case to snake case by default without explicitly annotating columns while saving objects to DB. Hence adding below property in application.properties worked for me:
spring.jpa.properties.hibernate.physical_naming_strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
Note: I am using spring boot version 2.6.2
Automatically transforming property-Names using camelCase (as is the naming convention in Java) to SNAKE_CASE seems to be no longer supported as of Hibernate 5. However, you can write your own Implementation of a NamingStrategy, doing exactly that.
Please check this Stackoverflow-Answer to see how it is done.

How to customize the spring-data Repository method names?

I've a bunch of entities that use an underscore prefix before the field names and otherwise use camelcase.
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long _id;
private String _firstName;
private String _lastName;
#OneToOne
private Foo _foo;
// … methods omitted
}
The repository
public interface CustomerRepository extends PagingAndSortingRepository<Customer, Long> {
Iterable<Customer> findByFoo(Foo foo);
}
The corresponding fields in the tables also use this naming scheme:
Customer: _id, _firstName, _lastName, _foo__id
Now that I am migrating this project to spring-data, I'm getting many IllegalArgumentExceptions with :
Could not create query metamodel for method
public abstract java.lang.Iterable
com.example.repository.CustomerRepository.findByFoo(com.example.model.Foo)!
Unable to locate Attribute with the given name [foo] on this ManagedType [com.example.model.Customer]
I have no need to change hibernate's naming strategy, but how can I change the query method generation naming algorithm to map "findByFoo" -> "_foo" on the entity, or in JPQL terms "where x._foo__id = ?1"
I'm using old school xml configuration, and no spring boot.
Edit: found this in the docs, which isn't helpful..
"As we treat underscore as a reserved character we strongly advise to
follow standard Java naming conventions (i.e. not using underscores in
property names but camel case instead)."
Perhaps I should refactor the field names, drop the underscore, and then implement a hibernate naming strategy that adds the underscore back in?
I can just repeat what's in the docs (although I'd be interested in the "isn't helpful" part). Use standard Java conventions for your Java code. Use the store specific means to customize the way properties are mapped onto database tables. JPA provides #Column annotations for that.

Path based on a non-PK unique field in spring-data-rest

Given an #Entity declared with the following fields:
#Id
private String idgeo;
private String isoCtryCd;
private String randomField;
with the default spring configuration I get resource paths ending with .../{idgeo}.
Is there an option in the spring configuration to use other (unique) fields as the resource path ending? In my example it'd be .../{isoCtryCd}
Thank you!
Actually this feature will be introduced in Spring Data Rest 2.5. Currently there is a 2.5.0.M1 milestone release containing this feature.
This part of the documentation shows how to use a different entity attribute for item resource uris.
http://docs.spring.io/spring-data/rest/docs/2.5.0.M1/reference/html/#_customizing_item_resource_uris

How to make a property injection via #Value annotation mandatory?

I have the following Test.java POJO class being populated from a property file using the #ConfigurationProperties annotation. I have seen the usage of #Required annotation to make it a mandatory.
Rather than defining annotations at the setter method level, are there any annotations or options within the #Value annotation that I can use for defining conditions like Mandatory, NotNull, etc?
#Component
#ConfigurationProperties(prefix = "com.test")
public class Test {
private String name;
#Required
public void setName(String name) {
name = name;
}
public String getName(String name) {
name = name;
}
}
Is this the right and only way for making a particular attribute mandatory? What are the other such annotations I could use for such conditions or validations purpose?
You can use validation for the properties, just not in the way you envisaged.
What you can do is use standard validation annotations (like #NotNull etc.) on the fields (or setters) themselves.
For example
#NotNull
#Size(min=2, max=10)
private String name;
Check out this part of the documentation
What the documentation essentially says, is that you simply have to have a compatible JSR303 validator implementation on the classpath, and use the relevant annotations.
Spring Boot will take care of the rest
According to the Spring docs (currently 4.1.6.RELEASE), the Value annotation only has a single property, value, containing the value of the property. You can put a Spring EL expression in this, but that won't let you explicitly express notions like non-nullity.
Further, in your code snippet you're using #ConfigurationProperties which is an alternative approach to configuring property values, compared to the #Value annotation.
The way you're doing it, your Java getter/setter names need to map to the property names, i.e. prefix "com.test" + getName() / setName() matches property com.test.name=...
So, you don't need the #Value annotation to tell Spring what property to use.
With the #Value approach, your getters/setters don't have to match the property names, but you do have to annotate each property e.g. #Value("${com.test.name}") and on the class, a #PropertySource annotation pointing to the properties file that contains com.test.name=...
I found a couple of blog posts with code examples that use the 2 different ways to inject the same properties: http://blog.codeleak.pl/2014/09/using-configurationproperties-in-spring.html and http://blog.codeleak.pl/2014/09/testing-mail-code-in-spring-boot.html

Categories