Closed MathieuAA closed 6 years ago
Please keep in mind, that changes in the JDL grammar affects the community which uses jhipster-ide. Since the ide features were introduced we have 300-500 installation per month and as you can imagine a change in the JDL would affect those people...
Beside of that, I also like the idea to improve the JDL grammar ;-) and thought to implement a kind of "Xjdl" (which stands for eXtended JDL) with feature similar to what you discussed in the issue #6275.
So I'm looking forward to this...
Colameo, the changes will be mostly backward compatible I believe
Yes. The only breaking change I've ever made was about regexes (the separator is now /
instead of '
).
@MathieuAA - ok that's good, that means we do not have pressure to integrate all changes in sync with yours.
@deepu105 I liked the abstract
and the type microservice
, this leaves other possibilities.
Deepu, I didn't get the difference between services
(plural) and service
singular in your post : https://github.com/jhipster/generator-jhipster/issues/6275#issuecomment-325188239. You wrote entity MyOnlyEntity
(singular) and services MyOnlyService
(plural). Is this a typo ?
entity MyOnlyEntity extends C { // one entity of the service extends one from commonConfig.jdl
// this will have the field name generated as it extends entity C
String code
}
services MyOnlyService {
Customer findByName(String name)
}
@agoncal it must be. @jhipster/developers, @bd82, @hakandilek My main goal this week will be to get the app generation up and running. This means being able to generate apps from one or more JDL files, without generating entities right after (this comes after).
@deepu105 Do you think it will be easy to update the subgen to make it generate an application?
@MathieuAA yes the import-jdl sub gen can be easily updated to compose the app sub gen based on the app configuration/yo-rc generated. Unfortunately, I'll be on vacation from tomorrow until 8th of September so I won't be of much help. I can, of course, review things from my phone. But this should be straight forward just follow the same way entity generator is composed.
@agoncal might be a typo, I meant singular/plural in the same meaning as you guys did. Also I would prefer to start with service creation and not repository as we already have a service sub gen to handle and also as per our policies it brings more value(repository can be easily hand created as its just adding method to an interface) for service we could create the service skeleton, a REST interface for that and so on. I guess you will achieve the same result that you expected with the repository keyword
@bd82 this is the autocomplete snippet we use. https://github.com/jhipster/jdl-studio/blob/gh-pages/js/codemirror/codemirror.jdl-mode.js
@deepu105 thanks for adding the syntax! I'll work on it this week and submit a PR.
@MathieuAA take look at the PR from @bd82 before you start as it might be useful
@deepu105 Yeah I've had a look yesterday, and I agree with you
@deepu105 I was thinking of your idea of "inheritance".
If you have a repository :
repository MyRepo {
int countByAge(int age);
}
With this code, you have a valuable repository (valuable, because you can use it and it works), it's associated service and REST controller. Everything works.
Now, for a service:
service MyService {
String myMethod(int param);
}
What do you do with it ? What do you generate ? And empty method ? What for ? You would have to add code on it. Coming back to your idea of inheritance, what about generating the following code:
public class MyService {
public abstract String myMethod(int param);
}
public class ExtendedMyService extends MyService {
@override
public String myMethod(int param) {
// add your code
}
}
This would allow to regenerate JHipster code easily (here, the MyService class) and creates an extension point for developers (using the ExtendedMyService).
WDYT ? Is that what you had in mind ?
@agoncal overall I would like to move to an Inheritance model for our generated code so that people can update the child classes without having to worry about being overwritten by upgrades and stuff.
Now for the repository vs Service. I belive if you generate a repo with say
repository MyRepo {
int countByAge(int age);
}
You would create a Spring Data Interface called MyRepo
with a method on it called countByAge
and you could generate a Spring service class called MyRepoService
with method countByAge
which calls MyRepo.countByAge
and a Rest Resource called MyRepoResource
with method countByAge
which calls MyRepoService.countByAge
(I hope this is what you meant) IMHO this is not very valuable as it wont take much effort or time to create the same using an IDE.
Exact same classes and methods can be generated by below as well
service MyService {
String myMethod(int param);
}
What I would rather prefer would be to be more flexible and provide a way to create service (as repository is too easy to hand code, just a spring data interface with methods) so you can do something like
service MyService {
String myMethod(int param)
Int countByAge(int age)
}
decorate MyService with repository, resource, serviceImpl
This will generate a resource class with end point for both methods (GET by default) the methods will call corresponding methods from service, an interface and impl for the service which will call repository methods. A spring repository. Here though its not too much value its faster to create different combinations and then customize it. And yes inheritance model would be nice on it as well
@deepu105 I agree that you can create Spring Data interface + service + REST controller using an IDE... but being able to do it in JDL is important.
The way I work with JHipster is that I never touch the generated code, and only use inheritance. This allows me to upgrade my projects. In in my JDL I have a :
repository MyRepo {
int countByAge(int age);
}
I know it will be in the generated code, and I know I won't have to touch it when upgrading JHipster. If you think of JHipster being an "IDE code generator", then, I can either use JHipster to generate a repository+service+controller or the IDE.
Services is where the business logic happens:
service MyService {
double myComplexCalculation()
}
With this code, there is not much you can do. For my model of programming (inheritance) this would not help me.
You idea of decoration is great. You could even go:
entity MyEntity {
String name
}
decorate MyEntity with repository, resource, serviceImpl
@deepu105 , everyone.
How large of an enrichment of the grammar are we talking about here?
I'm trying to figure out how the questions of:
If most of the Grammar will effectively be redesigned, we may want to answer the "How?" question first to avoid duplicate work.
If this enrichment mostly affects things outside the grammar and there will only be a moderate amount of syntax changes perhaps it does not matter and the tracks can be executed independently and in parallel.
Another idea is also to be able to generate Enums that are not related to Entity (see https://github.com/jhipster/jhipster-core/issues/167)
This part of the original issue was not brought over, so I copied it here:
Uniqueness
Today we have several validations on our attributes (required
, minlength
, maxlength
, pattern
). We could have unique
.
entity MyEntity {
myCode String unique,
myField String required,
mySecondField String
}
This would generate a @Column(unique = true)
as well as a Liquibase constraint :
<addUniqueConstraint columnNames="code"
tableName="mytable"
constraintName="my_unique_code"/>
Issue #18 also proposed unique constraints, but it actually went one step further, proposing a way to specify multi-column unique constraints, like so:
unique { entityA{columnA, columnB} }
This could then generate the composite unique constraint in Liquibase.
If you agree that this would be useful, I'd be happy to contribute this feature. However, being a jhipster rookie, could somebody point me in the right direction, like what are the parts that would need modifications?
All, I agree to the unique
thing as long as it doesn't look like unique { entityA{columnA, columnB} }
. If we implement it, we'd have to have this syntax for every field validation, and it just isn't right. A field validation is only relevant to a field, its field, not the class or the file.
The syntax should be:
entity A {
mySuperImportantField String required unique,
myNotSoImportantField Integer max(42),
myOtherImportantField unique
}
If it's implemented in the generator and the other JHipster devs agree to it (incidentally a PR for this would be nice in the generator), I'll add it to the JDL.
Now for this, a new issue should have been created (or posting in the first one) instead of adding yet another topic to this already impressive thread.
I guess we were clear in another thread that we won't afd unique validation as there is no added value. So for now it is out of scope lets not do it. Lets finish the basic grammar we agreed above and later we can think of other enhancements
@MathieuAA just tried JDL v2 : well done !
@agoncal did you try JDL v3? with the microservice stack generation https://github.com/jhipster/generator-jhipster/pull/8335
@deepu105 Current project is a monolith with Keycloak. Haven't had the chance to use microservices in v3... but will certainly give it a try ;o)
Hello, @MathieuAA
I need the notion of extends
andabstract
for entities at work. I will be able to watch the generator
part of this feature.
But I have some question:
entity.json
file?entity.json
file?BaseEntity
(https://github.com/jhipster/jhipster/pull/45) ?Let me disturb that conversation a little ^^ ;-).
If the goal of this new syntax is to ease JH upgrade without modifying code, it may be wise to focus on other aspects. If we take generated elements from the ground up:
May be adding a notion of extensibility on entities could be nice?
@sidebyside {
Service,
Repository,
Resource,
ClientService
}
entity ExtendedEntity {}
Or even better being inspired by the EMF XCore like or VPDSL syntax
@generation {
Entity(skip), //skip|true defaults to true
Repository ([{jpa: decorate}, {search: true}], //skip|true|decorate defaults to true
DTO({mapstruct: decorate}), //skip|true|decorate defaults to true
Service (impl, decorate), //impl|class|decorate defaults to class
Resource(decorate), //true|decorate defaults to true
ClientService(decorate) //true|decorate defaults to true
}
entity ExtendedEntity {}
With one or the other, we could avoid the 'repository' and 'service' keyword which are in this form kind of overkill for what they achieve IMHO.
Also, I really like the notion of generic definition extension and abstraction, which would be very useful in many cases, circumventing the actual impossibility to have the same entity in two microservices which is frequent when doing client-server.
I'm finally inline with the point of cbornet: we should be able to host a full microservice definition by jdl file, which is impossible today, due to the generic configurations like search, skipClient, and so on. May be a little trick concatenating every imported jh values for a property could do the trick.
I have been working on some JDL syntax and feature enhancements. Ill share them soon, for the record I don't want to change any existing syntax, I think they are quite simple and nice, which is more important. Let me write up about what I have in mind later.
closing in favor of https://github.com/jhipster/jhipster-core/issues/277
From the generator's original post here
Syntax in consideration:
commonConfig.jdl
myMicroservice1JDLFile.jdl
myGateway.jdl
This will generate