jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.51k stars 4.02k forks source link

Issue on Front side when using skipClient for some entities #13305

Closed DanielFran closed 3 years ago

DanielFran commented 3 years ago
Overview of the issue

Issue with declaration of model on front for entities that have been skipped

Motivation for or Use Case

On front-end, it is declared model for all one-to-many entities but some of them are defined to be 'skipped' on the front side.

[INFO] ERROR Failed to compile with 1 errors12:11:41 [INFO] [INFO] error
[INFO] [INFO] src/main/webapp/app/entities/symptom/symptom.model.ts:1:31 - error TS2307: Cannot find module 'app/entities/toxicity-rate/toxicity-rate.model' or its corresponding type declarations. [INFO] [INFO] 1 import { IToxicityRate } from 'app/entities/toxicity-rate/toxicity-rate.model'; [INFO] ~~~~~~~~~~~~ [INFO] src/main/webapp/app/entities/drug/drug.model.ts:1:25 - error TS2307: Cannot find module 'app/entities/notice/notice.model' or its corresponding type declarations. [INFO] [INFO] 1 import { INotice } from 'app/entities/notice/notice.model'; [INFO] ~~~~~~~~~~

JHipster Version(s)

Using main branch.

JHipster configuration
JHipster Version(s)
supportivecare@1.2.0-SNAPSHOT C:\REDCATS\Mestrado UC\3 Semestre\Studio\MSE-2019-2021\support_care
+-- generator-jhipster@6.10.5
`-- generator-jhipster-entity-audit@3.3.0
  `-- generator-jhipster@6.10.5  deduped
JHipster configuration, a .yo-rc.json file generated in the root folder
.yo-rc.json file
{
  "generator-jhipster": {
    "authenticationType": "jwt",
    "cacheProvider": "caffeine",
    "clientFramework": "angularX",
    "serverPort": "8080",
    "serviceDiscoveryType": false,
    "skipUserManagement": false,
    "withAdminUi": false,
    "baseName": "supportivecare",
    "buildTool": "maven",
    "databaseType": "sql",
    "devDatabaseType": "h2Memory",
    "enableHibernateCache": true,
    "enableSwaggerCodegen": false,
    "enableTranslation": true,
    "jhiPrefix": "custom",
    "languages": ["pt-pt", "en"],
    "messageBroker": false,
    "prodDatabaseType": "postgresql",
    "searchEngine": false,
    "skipClient": false,
    "testFrameworks": ["cypress"],
    "websocket": false,
    "applicationType": "monolith",
    "packageName": "uc.dei.mse.supportivecare",
    "packageFolder": "uc/dei/mse/supportivecare",
    "clientPackageManager": "npm",
    "nativeLanguage": "pt-pt",
    "jhipsterVersion": "6.10.5",
    "skipServer": false,
    "dtoSuffix": "DTO",
    "entitySuffix": "",
    "reactive": false,
    "clientTheme": "none",
    "clientThemeVariant": "",
    "entities": [
      "Administration",
      "Notice",
      "Drug",
      "Treatment",
      "TherapeuticRegime",
      "Document",
      "Content",
      "Outcome",
      "ToxicityRate",
      "Symptom",
      "Feedback"
    ],
    "skipCheckLengthOfIdentifier": false,
    "skipFakeData": false,
    "blueprints": [],
    "otherModules": [],
    "pages": [],
    "creationTimestamp": 1608113073245,
    "jwtSecretKey": "YourJWTSecretKeyWasReplacedByThisMeaninglessTextByTheJHipsterInfoCommandForObviousSecurityReasons",
    "lastLiquibaseTimestamp": 1608113733000
  },
  "generator-jhipster-entity-audit": {
    "auditFramework": "custom",
    "auditPage": false,
    "lastLiquibaseTimestamp": 1608113656000
  }
}

JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory
JDL entity definitions
/**
 * Administração.
 */
entity Administration {
  /**
   * Tipo de administração.
   */
  type String required maxlength(100)
}
/**
 * Observação.
 */
entity Notice {
  /**
   * Descrição.
   */
  description String required maxlength(1000),
  /**
   * Avaliação.
   */
  evaluation String required maxlength(1000),
  /**
   * Intervenção interdependente.
   */
  intervention String required maxlength(1000)
}
/**
 * Medicamento.
 */
entity Drug {
  /**
   * Nome.
   */
  name String required maxlength(250),
  /**
   * Descrição geral.
   */
  description String maxlength(1000)
}
/**
 * Tratamento.
 */
entity Treatment {
  /**
   * Tipo de tratamento.
   */
  type String required maxlength(100)
}
/**
 * Regime Terapêutico.
 */
entity TherapeuticRegime {
  /**
   * Nome.
   */
  name String required maxlength(250),
  /**
   * Acrônimo.
   */
  acronym String maxlength(50),
  /**
   * Propósito.
   */
  purpose String required maxlength(1000),
  /**
   * Condições para administração.
   */
  condition String required maxlength(1000),
  /**
   * Calendarização.
   */
  timing String maxlength(250),
  /**
   * Indicação para prescrição.
   */
  indication String required maxlength(1000),
  /**
   * Critérios de redução de dose.
   */
  criteria String required maxlength(1000),
  /**
   * Outras informações.
   */
  notice String maxlength(1000)
}
/**
 * Documento.
 */
entity Document {
  /**
   * Título.
   */
  title String required maxlength(250),
  /**
   * Tamanho.
   */
  size Long required,
  /**
   * Tipo de ficheiro.
   */
  mimeType String maxlength(50)
}
/**
 * Conteúdo.
 */
entity Content {
  /**
   * Dados.
   */
  data AnyBlob required
}
/**
 * PROM.
 */
entity Outcome {
  /**
   * Nome.
   */
  name String required maxlength(250),
  /**
   * Descrição.
   */
  description String maxlength(1000)
}
/**
 * Grau de Toxicidade.
 */
entity ToxicityRate {
  /**
   * Nome.
   */
  name String required maxlength(250),
  /**
   * Descrição.
   */
  description String maxlength(1000),
  /**
   * Informação ao doente.
   */
  notice String maxlength(1000),
  /**
   * Intervenção autónoma.
   */
  autonomousIntervention String maxlength(1000),
  /**
   * Intervenção interdependente.
   */
  interdependentIntervention String maxlength(1000),
  /**
   * Suporte para auto-gestão.
   */
  selfManagement String maxlength(1000)
}
/**
 * Sintoma (Efeito secundário).
 */
entity Symptom {
  /**
   * Nome.
   */
  name String required maxlength(250),
  /**
   * Informação ao enfermeiro.
   */
  notice String maxlength(1000)
}
/**
 * Feedback.
 */
entity Feedback {
  /**
   * Nome da entidade.
   */
  entityName EntityFeedback required,
  /**
   * Id da entidade.
   */
  entityId Long required,
  /**
   * Polegar.
   */
  thumb Boolean required,
  /**
   * Razão.
   */
  reason String maxlength(1000),
  /**
   * Resolvido.
   */
  solved Boolean required,
  /**
   * Anónimo.
   */
  anonym Boolean required
}
enum EntityFeedback {
  DRUG (Drug),
  THERAPEUTIC_REGIME (TherapeuticRegime),
  OUTCOME (Outcome),
  SYMPTOM (Symptom)
}

relationship OneToOne {
  Document{content} to Content{document required}
}
relationship OneToMany {
  Drug{notice(description)} to Notice{drug(name) required},
  Administration{drug} to Drug{administration(type) required},
  Treatment{therapeuticRegime} to TherapeuticRegime{treatment(type) required},
  Outcome{document} to Document{outcome(name) required},
  Symptom{toxicityRate(name)} to ToxicityRate{symptom(name)}
}
relationship ManyToMany {
  TherapeuticRegime{drug(name)} to Drug{therapeuticRegime(name)},
  Symptom{therapeuticRegime(name)} to TherapeuticRegime{symptom(name)},
  Symptom{outcome(name)} to Outcome{symptom(name)}
}

dto Administration, Notice, Drug, Treatment, TherapeuticRegime, Document, Content, Outcome, ToxicityRate, Symptom, Feedback with mapstruct
paginate Administration, Notice, Drug, Treatment, TherapeuticRegime, Document, Content, Outcome, ToxicityRate, Symptom, Feedback with infinite-scroll
service Administration, Notice, Drug, Treatment, TherapeuticRegime, Document, Content, Outcome, ToxicityRate, Symptom, Feedback with serviceClass
filter Administration, Notice, Drug, Treatment, TherapeuticRegime, Document, Content, Outcome, ToxicityRate, Symptom, Feedback

Environment and Tools

java version "11.0.8" 2020-07-14 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.8+10-LTS) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.8+10-LTS, mixed mode)

git version 2.24.1.windows.2

node: v14.15.1

npm: 6.14.9

yeoman: 3.1.1

Docker version 20.10.0, build 7287ab3

docker-compose version 1.27.4, build 40524192

identical .jhipster\Administration.json identical .jhipster\Content.json identical .jhipster\Document.json identical .jhipster\Drug.json identical .jhipster\Feedback.json identical .jhipster\Notice.json identical .jhipster\Outcome.json identical .jhipster\Symptom.json identical .jhipster\TherapeuticRegime.json identical .jhipster\ToxicityRate.json identical .jhipster\Treatment.json INFO! Congratulations, JHipster execution is complete!- [ ] Checking this box is mandatory (this is just to show you read everything)

DanielFran commented 3 years ago

@kaidohallik @mshima Do not know if it is related with Angular only and the refactoring, or related with changes on entities....

Issue related with:

relationship OneToMany { Drug{notice(description)} to Notice{drug(name) required}, Symptom{toxicityRate(name)} to ToxicityRate{symptom(name)} }

And in original jdl I have also declared to skip some entities: skipClient Notice, ToxicityRate

But on the 'jhipster info' it did not appears!

kaidohallik commented 3 years ago

I tried the same config with Vue. Vue compiles successfully, but the same error occurs in runtime in Vue after entering to page that includes this import, this model is not generated also in Vue client. So seems that general problem, not related to Angular.

mshima commented 3 years ago

If the jdl works on jhipster 6, then it’s because of the flatten dto. At jhipster 7, entities always depends on the model of the other entity. Drug is not skipClient but it uses notice model that is skipClient. In this case at least the model file must be written.

mshima commented 3 years ago

In this case we should try to support single side relationships:


relationship ManyToOne {
Notice{drug(name) required} to Drug,
ToxicityRate{symptom(name)} to Symptom
}

And drop back reference.

mshima commented 3 years ago

cc @MathieuAA

kaidohallik commented 3 years ago

FYI: if I look at Vue source then there is also used .service file for skipClient entity, so for Vue also .service file is needed.

pascalgrimaud commented 3 years ago

After discussing with @MathieuAA about this, here my opinion:

So if I understand well, we should do a new option: --skipClientButGenerateModelAndService :-D

I think it's faster to generate everything (without skipping client), and then:

skipClient and skipServer are for very advanced use cases. It can't work out of the box, you need to modify the generated code.

mshima commented 3 years ago

I’m in favor of supporting single sided relationships. Back reference would not be written and models would be independent.

mshima commented 3 years ago

@DanielFran can you confirm if manually removing Notice relationship from .jhipster/Drug.json and Symptom relationship from .jhipster/ToxicityRate.json it generates the application you want?

DanielFran commented 3 years ago

@pascalgrimaud There is in fact 2 possibilities:

What ever solution chosen, both backend and front-end should build.

@mshima In my case I wan't to include in front-end a list of notices in drug page detail.

pascalgrimaud commented 3 years ago

What ever solution chosen, both backend and front-end should build.

Not sure about that. When using skipClient + skipServer, it's not supposed to work out of the box. You always need to do some work after generating that. The proof is: we don't have the CI to test this part, as skipClient + skipServer are only for very advanced uses, so the end-user knows what he/she's doing.

But we can discuss about it of course :)

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted. We are accepting PRs :smiley:. Comment or this will be closed in 7 days

egvimo commented 3 years ago

I have the same issue. I've created a simple example to reproduce it.

Here is the JDL:

application {
    config {
        baseName sample
        packageName sample
        applicationType monolith
        authenticationType oauth2
        buildTool gradle
        clientFramework angularX
        prodDatabaseType postgresql
        devDatabaseType postgresql
    }
    entities *
}

entity Abc {
    name String unique required
}

@skipClient
entity Xyz {
    name String unique required
}

relationship OneToMany {
    Abc{children} to Xyz{parent}
}

The generated Code with the error:

import { IXyz } from 'app/entities/xyz/xyz.model'; // Error

export interface IAbc {
  id?: number;
  name?: string;
  children?: IXyz[] | null; // Error
}

export class Abc implements IAbc {
  constructor(public id?: number, public name?: string, public children?: IXyz[] | null) {}
}

Is it possible to fix this?

mshima commented 3 years ago

Is it possible to fix this?

egvimo commented 3 years ago

This doesn't work. The generator overwrites the json files and regenerates the faulty model files.

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Our core developers tend to be more verbose on denying. If there is no negative comment, possibly this feature will be accepted. We are accepting PRs :smiley:. Comment or this will be closed in 7 days

egvimo commented 3 years ago

This is issue is still relevant to me.

MathieuAA commented 3 years ago

Frankly if the PR #14461 is for this issue, I'm against it. cc @mshima for the same reasons @pascalgrimaud explained.


edit: I see it still has the "needs-discussion" label too.

mshima commented 3 years ago

@MathieuAA I didn't implemented to fix this issue, but for:

  1. Reduce generated code.
  2. If a back-reference will not be used, it useless increases complexity of the application and is more error prone. Quoting @gzsombor at https://github.com/jhipster/generator-jhipster/issues/13885:
    If I add a Node{mainOther} to OtherEntity{reverseMains} - then it will generate the entities, however, that will add a Set<Node> reverseMains to OtherEntity, which I would like to avoid, as doesn't make too much sense, and could accidentally trigger unwanted db queries, etc
  3. Avoids unnecessary conflicts like:
    entity A {}
    entity B {}
    relationship ManyToOne {
    A{firstB} to B // back-reference called a
    A{secondB} to B // back-reference called a
    }

I would implement a blueprint to remove back references for personal use but there is no way to differ autogenerated back references.

mshima commented 3 years ago

And according to the documentation https://www.jhipster.tech/managing-relationships/ unidirectional ARE supported.

https://www.jhipster.tech/managing-relationships/#a-unidirectional-many-to-one-relationship https://www.jhipster.tech/managing-relationships/#a-unidirectional-one-to-one-relationship

So IMO this should be provided by default, not only optional like the PR implements.

MathieuAA commented 3 years ago

Avoids unnecessary conflicts like:

It can easily be done at JDL level.

I agree unidirectional rels are supported, I'm not saying the opposite :) do keep in mind that I very probably wrote the doc you're referencing ;) The main reasons unidirectional relationships are supported is because there are many use cases where it's the right way to model relationships. The same goes for bidirectional ones BTW. The last time I checked there still were cases where unidirectional rels weren't supported because of issues regarding hibernate (I may be wrong though).

Here, I just don't see how implementing it would solve this issue's issue. I may need to read it all over again.

mshima commented 3 years ago

Here, I just don't see how implementing it would solve this issue's issue. I may need to read it all over again.

It doesn't actually fixes the this issue, but adds a way to workaround it by changing from:

relationship OneToMany {
  Drug{notice(description)} to Notice{drug(name) required},
  Symptom{toxicityRate(name)} to ToxicityRate{symptom(name)}
}

skipClient Notice, ToxicityRate

to:

relationship ManyToOne {
  Notice{drug(name) required} to Drug
  ToxicityRate{symptom(name)} to Symptom
}

skipClient Notice, ToxicityRate

A fix would be to skip the relationship if the otherEntity is @SkipClient. But IMO frontend models should match backend models.