Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LazyInitializationException on an entity with ManyToMany, pagination and mapstruct #5629

Closed
1 task done
Falydoor opened this issue Apr 20, 2017 · 48 comments
Closed
1 task done

Comments

@Falydoor
Copy link
Contributor

Overview of the issue

Hibernate throws an exception when trying to get all Job entities after creating a Job entity.

Exception in com.jhipster.web.rest.JobResource.getAllJobs() with cause = 'NULL' and exception = 'failed to lazily initialize a collection of role: com.jhipster.domain.Job.tasks, could not initialize proxy - no Session'

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.jhipster.domain.Job.tasks, could not initialize proxy - no Session
	at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
	at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
	at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561)
	at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132)
	at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:163)
	at com.jhipster.service.mapper.JobMapperImpl.taskSetToTaskDTOSet(JobMapperImpl.java:140)
	at com.jhipster.service.mapper.JobMapperImpl.jobToJobDTO(JobMapperImpl.java:58)
	at com.jhipster.service.mapper.JobMapperImpl.jobsToJobDTOs(JobMapperImpl.java:81)
Motivation for or Use Case

This issue only appears when having an entity with a ManyToMany relationship, being paginated (pager, pagination or infinite-scroll) and dto generated with mapstruct.
It's a little specific but if you use the default JDL from JDL Studio you will have the issue.

Reproduce the error

Use the JDL below to generate entities.
Create a Job entity with no Task.
An exception will be thrown when displaying all Job.

Related issues

Found nothing related.

Suggest a Fix

Maybe by doing an eager load on the ManyToMany relationship like it's done when Job is not paginated.

JHipster Version(s)

4.3.0

JHipster configuration
JHipster Version(s)
jhipster@0.0.0 /Users/Theo/Documents/perso/jhipster-issues
└── generator-jhipster@4.3.0

JHipster configuration, a .yo-rc.json file generated in the root folder
{
  "generator-jhipster": {
    "promptValues": {
      "packageName": "com.jhipster"
    },
    "jhipsterVersion": "4.3.0",
    "baseName": "jhipster",
    "packageName": "com.jhipster",
    "packageFolder": "com/jhipster",
    "serverPort": "8080",
    "authenticationType": "session",
    "hibernateCache": "ehcache",
    "clusteredHttpSession": false,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "prodDatabaseType": "mysql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": false,
    "buildTool": "maven",
    "enableSocialSignIn": false,
    "rememberMeKey": "2b4523900caffa3f139b0240dc516cfd9735ba18",
    "clientFramework": "angular1",
    "useSass": false,
    "clientPackageManager": "yarn",
    "applicationType": "monolith",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "enableTranslation": false
  }
}
Entity configuration(s) entityName.json files generated in the .jhipster directory

Job.json

{
    "fluentMethods": true,
    "relationships": [
        {
            "relationshipType": "many-to-many",
            "otherEntityRelationshipName": "job",
            "relationshipName": "task",
            "otherEntityName": "task",
            "otherEntityField": "id",
            "ownerSide": true
        }
    ],
    "fields": [
        {
            "fieldName": "jobTitle",
            "fieldType": "String"
        }
    ],
    "changelogDate": "20170420032832",
    "entityTableName": "job",
    "dto": "mapstruct",
    "pagination": "pagination",
    "service": "no"
}

Task.json

{
    "fluentMethods": true,
    "relationships": [
        {
            "relationshipType": "many-to-many",
            "relationshipName": "job",
            "otherEntityName": "job",
            "ownerSide": false,
            "otherEntityRelationshipName": "task"
        }
    ],
    "fields": [
        {
            "fieldName": "title",
            "fieldType": "String"
        }
    ],
    "changelogDate": "20170420032831",
    "entityTableName": "task",
    "dto": "mapstruct",
    "pagination": "no",
    "service": "no"
}
Browsers and Operating System

java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

git version 2.10.1 (Apple Git-78)

node: v7.8.0

npm: 4.2.0

bower: 1.8.0

gulp:
[23:47:04] CLI version 1.2.2
[23:47:04] Local version 3.9.1

yeoman: 1.8.5

yarn: 0.22.0

Docker version 17.03.1-ce, build c6d412e

docker-compose version 1.11.2, build dfed245

Entity configuration(s) entityName.json files generated in the .jhipster directory

JDL

entity Task {
	title String
}

entity Job {
	jobTitle String
}

relationship ManyToMany {
	Job{task} to Task{job}
}

paginate Job with pagination
dto * with mapstruct
Browsers and Operating System

Chrome 57 on OS X El Capitan

  • Checking this box is mandatory (this is just to show you read everything)
@jdubois
Copy link
Member

jdubois commented Apr 20, 2017

+1
Not sure of what we can do here, but we shouldn't have a configuration that fails out of the box

@vw98075
Copy link
Contributor

vw98075 commented Apr 20, 2017

The lazy initialization is a right approach. For such problem, a service layer would do its duty, fetching all data needed for the client which can have more than one DB calls. You don't need to fetch children entities only if you in the Hibernate session. A Hibernate session won't be kept alive in the modern web application architecture after fetching a parent entity.

@jlgc77
Copy link

jlgc77 commented May 17, 2017

If you change the line:
"service all with serviceImpl except Employee, Job"
by:
"service all with serviceImpl"

If "Job" has service, it works correctly

@xetys
Copy link
Member

xetys commented May 28, 2017

the question here is:

  1. should that be fixed? This is a quite specific case, and I'm sure, there are more combinations which lead to similar issues with JPA and co
  2. should that special case be fixed using EAGER fetch type?
  3. or using repository queries, where the sub-entities are explicitly fetched

@cbornet
Copy link
Member

cbornet commented May 28, 2017

I think that the original issue is that we try to serialize a "many" collection which is both an issue with lazy loading and for performance if the collection gets important. For instance on OneToMany relationship we hide the collection from the response.
Shouldn't we output a link to the collection instead in a very RESTful way ? This way, when the client calls the link we can apply proper pagination. And it could be applied to OneToMany relationships also.
The link could be something like /jobs/{id}/tasks

@Codefans-fan
Copy link

any result?

@jdubois
Copy link
Member

jdubois commented Jul 5, 2017

Please @Codefans-fan don't spam everyone if you don't work on the issue.
If anything had been done, it would be written here.

@ctamisier
Copy link
Contributor

ctamisier commented Jul 5, 2017

The problem remains intact when using a service.
The generated Service classes are @Transactional so the request the get the tasks is performed in the
for ( Task task : set ) { (loop in JobMapperImpl).
Which actually leads to an N+1 selects problem the get all the jobs with all its tasks (that can be "solved" by a @BatchSize like in the User class for the authorities).

And with no service it fails because the transaction is done.

A solution could be to have in EntityMapper class:

  • public D toDtoLazy(E entity); (with an @Mapping(ignore=true) for the lazy collection)
  • public List <D> toDtoLazy(List<E> entityList); (and apply a mapstruct Qualifier to pick up the above mapping method instead of the 'default' one)

There is a discussion about this: mapstruct/mapstruct#778

@ctamisier
Copy link
Contributor

JobMapper can be like this:

@Mapper(componentModel = "spring", uses = {TaskMapper.class, })
public interface JobMapper extends EntityMapper <JobDTO, Job> {

    @Named("lazy")
    @Mapping(target = "tasks", ignore = true)
    JobDTO toDtoLazy(Job entity);

    @IterableMapping(qualifiedByName = "lazy")
    List<JobDTO> toDtoLazy(List<Job> entityList);

    default Job fromId(Long id) {
        if (id == null) {
            return null;
        }
        Job job = new Job();
        job.setId(id);
        return job;
    }
}

and in JobResource.getAllJobs method:

return new ResponseEntity<>(jobMapper.toDtoLazy(page.getContent()), headers, HttpStatus.OK);

@gmarziou
Copy link
Contributor

gmarziou commented Jul 5, 2017

@ctamisier I don't think we can address all use cases, your approach with toDtoLazy works for one relationship, what if you have several ones and some of them are bi-directional or creating a cycle?
Also, if you want to have efficient queries you should probably use @NamedEntityGraph, so more code in entities and repositories.

I think this is the case where you must write ad-hoc mapper code and MapStruct just gets in your way.

I like @cbornet RESTful approach, it would produce a very intuitive swagger doc.

@deepu105 and @sendilkumarn this is the kind of tips that would be very useful in a JHipster book ;)

@cbornet
Copy link
Member

cbornet commented Jul 6, 2017

Other advantages of the REST link:

  • solves the N+1 select issue
  • solves the circular ref issue so we can have the link also for the non owner side of the many-to-many

For the form, it could be done as an HATEOAS-compliant links property in the response:
GET /api/jobs (paginated)

[ {  
    "id": 1001,
    "jobTitle": "some job",
    "links": [ {
        "rel": "tasks",
        "href": "http://localhost:8080/api/jobs/1001/tasks"
    } ]
  },
  {  
    "id": 1003,
    "jobTitle": "some other job",
    "links": [ {
        "rel": "tasks",
        "href": "http://localhost:8080/api/jobs/1003/tasks"
    } ]
  }
]

GET /api/tasks (not paginated)

[ {  
    "id": 1002,
    "title": "some task",
    "links": [ {
        "rel": "jobs",
        "href": "http://localhost:8080/api/tasks/1002/jobs"
    } ]
} ]

GET /api/tasks/1002/jobs (paginated) where task 1002 is linked to job 1001 but not to job 1003

[ {  
    "id": 1001,
    "jobTitle": "some job",
    "links": [ {
        "rel": "tasks",
        "href": "http://localhost:8080/api/jobs/1001/tasks"
    } ]
} ]

@ctamisier
Copy link
Contributor

yes very good.
But we will still need a WS to have all the jobs with all its tasks in only one GET http call.
(like we currently have with the list of users with all theirs authorities in one page)

@cbornet
Copy link
Member

cbornet commented Jul 7, 2017

@ctamisier if you mean eager fetching for performance reason because the client is sure to need the info, then this shouldn't be the default and I'm not sure we should generate something for that.

@cbornet
Copy link
Member

cbornet commented Jul 7, 2017

@jhipster/developers if we agree on the links, I can do the work for the backend but I would probably need help for the front... For instance, on the grid, the "many" value should probably be a link to the child grid filtered on the parent instead of the list of child IDs as we do currently.

@gzsombor
Copy link
Member

gzsombor commented Jul 7, 2017

For the backend, you don't need to do a lot of thing, after #5540 , the entity listing will be improved with filtering, so you can call : /api/tasks?jobId.equals=1001 and it will return the matching "tasks".
However, from the performance point of view, adding an extra REST call is bad, the latency will kill the user experience.

@cbornet
Copy link
Member

cbornet commented Jul 7, 2017

@gzsombor that's the point of outputting a link : no automatic fetching of the child collections, only one HTTP query, only one Hibernate call.

@gzsombor
Copy link
Member

gzsombor commented Jul 7, 2017

But the browser still needs to issue a separate HTTP query to fetch the entities, isn't it ?

@cbornet
Copy link
Member

cbornet commented Jul 7, 2017

It depends on what you display in the browser 😃
For instance I don't think our current way of displaying all the child IDs is good if there is a lot of children (imagine if there are millions of them...). That's why I suggest to replace it by a link to a grid of the children filtered for the parent with proper pagination.

@cbornet
Copy link
Member

cbornet commented Jul 9, 2017

@gzsombor will the criteria filtering work with many-to-many relationships ?

@cbornet
Copy link
Member

cbornet commented Jul 10, 2017

I just realized that many-to-many are currently fetched eagerly in the repository (findAllWithEagerRelationships, findOneWithEagerRelationships). I don't think this is a good idea:

  • LAZY should always be the default
  • Eagerly fetching one level will not save you from LazyInitializationException if the graph is more than one level (A has many B, B has many C, ...)

@ctamisier
Copy link
Contributor

findAllWithEagerRelationships is available but not used by default
findOneWithEagerRelationships is used by default in the *Service.findOne

LAZY should always be the default

Yes, LAZY should be by default (it is currently the case) but the use findAllWithEagerRelationships and findOneWithEagerRelationships is required depending the cases:

If we have: Job <-*---*-> Task:

  • the use of findOneWithEagerRelationships is justified because it is exactly what we want: the job with its tasks because we need to 'view' or 'edit' them in the according page.
  • the use of findAllWithEagerRelationships could be justified if we need all the jobs with all the tasks in the jobs list page.

If we have: Job <-*---*-> Task and Job <-*---*-> Employee:

  • the use of findOneWithEagerRelationships and findAllWithEagerRelationships is not correct for me because the result of the SQL request will have N*M lines (number of job-task relations * number of job-employee relations).

Eagerly fetching one level will not save you from LazyInitializationException if the graph is more than one level (A has many B, B has many C, ...)

True when we don't use DTO otherwise the methods in *Service class are @Transactionnal and the mapping entity to DTO is done here (which causes eventual extra SQL requests) and the database can be hit at any time during this transaction (but can be suboptimal and having N+1 selects)

All this to say that I would keep findAllWithEagerRelationships and findOneWithEagerRelationships (and eventually make a different request when we have more than one @ManyToMany relationships)

@gmarziou
Copy link
Contributor

gmarziou commented Jul 10, 2017

N+1 queries are not necessary bad when your related entities can be easily cached and don't change often.
Just to say that we cannot cover all use cases and that our users are developers so they must understand the pros and cons in their business context.

@ctamisier
Copy link
Contributor

Yes you're right.
In this case for this current issue should we just add @Transactional to the Rest Controllers that don't have a service to have this working out of the box ?

@gzsombor
Copy link
Member

@cbornet : in the current patch, the many-to-many relations are not covered yet (only the one-to-one and many-to-one), but it's fairly simple to add them.

@cbornet
Copy link
Member

cbornet commented Jul 10, 2017

@ctamisierfindAllWithEagerRelationships is used. See https://github.com/jhipster/generator-jhipster/blob/master/generators/entity/templates/server/src/main/java/package/common/get_all_template.ejs#L30.
Again, what I'm saying is not that eager fetching is not sometimes the best solution but that it should be avoided if possible. As such JHipster generated code should avoid it and probably not generate it.
Here is the query used for TestManyToMany:

    @Query("select distinct test_many_to_many from TestManyToMany test_many_to_many left join fetch test_many_to_many.testEntities left join fetch test_many_to_many.testMapstructs left join fetch test_many_to_many.testServiceClasses left join fetch test_many_to_many.testServiceImpls left join fetch test_many_to_many.testInfiniteScrolls left join fetch test_many_to_many.testPagers left join fetch test_many_to_many.testPaginations left join fetch test_many_to_many.testCustomTableNames")
    List<TestManyToMany> findAllWithEagerRelationships();

I'm pretty sure that's inefficient.
I'd rather have the user fetch the child collection he wants with another query. Or write his query by himself depending on his business context as @gmarziou said.
So for me, default = lazy. If the user wants eager for his own valuable reasons, he writes the code himself.
As for the JHipster generated code, I'd adapt the "List all" view to use only one lazy request and present links to view the child collections.

@jdubois
Copy link
Member

jdubois commented Aug 6, 2017 via email

@cbornet
Copy link
Member

cbornet commented Aug 6, 2017

My position is still the same :

  • we should not fetch the child collections in our generated endpoints. (JsonIgnore)
  • we should provide other endpoints to fetch those collections (eg. /jobs/{id}/tasks)
  • we should adapt our generated frontend to those endpoints. (eg. not displaying the list of child ids in the grid but a link to a grid of them)

The main problem for that approach would be generation since we don't know which entities point to the entity we are generating.(we know if a one-to-many is unidir when generating the many side since it's the owner of the relationship in this case, and not when the rel is bidir)

@cbornet
Copy link
Member

cbornet commented Aug 8, 2017

I started to look at what would need to be generated to have child collections fetch endpoints.
@gzsombor 's filter endpoints would be nice to use but as of now they are optional and don't support many-to-many.
So writing new resource code, this gives for bidir OneToMany
JDL

entity Car {
  name String
}

entity Person {
  name String
}

relationship OneToMany {
  Person{ownedCar} to Car{owner},
  Person{drivenCar} to Car{driver}
}

CarResource.java

    /**
     * GET  /people/:id/owned-cars : get the owned-cars for the owner "id".
     *
     * @param id the id of the person for which to get the owned-cars
     * @return the list of owned-cars for the person "id"
     */
    @GetMapping("/people/{id}/owned-cars")
    @Timed
    public ResponseEntity<List<CarDTO>> getCarsByOwnerId(@PathVariable Long id, @ApiParam Pageable pageable) {
        log.debug("REST request to get owned-cars for person : {}", id);
        Person person = new Person();
        person.setId(id);
        Page<Car> page = carRepository.findByOwner(person, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/people/" + id + "/owned-cars");
        return new ResponseEntity<>(carMapper.toDto(page.getContent()), headers, HttpStatus.OK);
    }

    /**
     * GET  /people/:id/driven-cars : get the driven-cars for the driver "id".
     *
     * @param id the id of the person for which to get the driven-cars
     * @return the list of driven-cars for the person "id"
     */
    @GetMapping("/people/{id}/driven-cars")
    @Timed
    public ResponseEntity<List<CarDTO>> getCarsByDriverId(@PathVariable Long id, @ApiParam Pageable pageable) {
        log.debug("REST request to get driven-cars for person : {}", id);
        Person person = new Person();
        person.setId(id);
        Page<Car> page = carRepository.findByDriver(person, pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/people/" + id + "/cars");
        return new ResponseEntity<>(carMapper.toDto(page.getContent()), headers, HttpStatus.OK);
    }
  • The problem is that currently it cannot be generated since the many side doesn't know the otherEntityRelationshipName. It would have to be a new question.
  • The ManyToMany code is pretty much the same.

As for hypermedia links if we want to add them for documentation/ease-of-use, it's easy to add them using spring-hateoas.
PersonResource.java

    @GetMapping("/people/{id}")
    @Timed
    public ResponseEntity<PersonDTO> getPerson(@PathVariable Long id) {
        log.debug("REST request to get Person : {}", id);
        Person person = personRepository.findOne(id);
        PersonDTO personDTO = personMapper.toDto(person);
        if (personDTO != null) {
            personDTO.getLinks().add(linkTo((methodOn(CarResource.class).getCarsByDriverId(person.getId(), null))).withRel("drivenCars"));
            personDTO.getLinks().add(linkTo((methodOn(CarResource.class).getCarsByOwnerId(person.getId(), null))).withRel("ownedCars"));
        }
        return ResponseUtil.wrapOrNotFound(Optional.ofNullable(personDTO));
    }

which will output for GET http://localhost:8080/api/people/1

{
  "id": 1,
  "name": "qrehgtrh",
  "links": [
    {
      "rel": "drivenCars",
      "href": "http://localhost:8080/api/people/1/driven-cars"
    },
    {
      "rel": "ownedCars",
      "href": "http://localhost:8080/api/people/1/owned-cars"
    }
  ]
}

@gzsombor
Copy link
Member

gzsombor commented Aug 8, 2017

Sorry, I've started implementing the many-to-many stuff, the library part is done, here. After it's merged, and a new release is made, then the generator can be adjusted.

For the two-way references between a many-to-many relation (or with any other type of relation), is not solved automatically. Maybe we could re-generate both the entities in this case?

Other than, I don't get why this hateoas thing is good. Yes, with generating that many links, you could have a very generic client, which could automatically download a lots of entities, without knowing the meaning of them. Which is nice, if you want to crawl your site :-) But if you develop an actual client, then you will know, that people entity have 'drivenCars' and 'ownedCars' property, and in this case, following REST rules, you could be expecting them reachable under {entity URL}/driverCars and {entity URL}/ownedCars, instead of this additional indirection. If not, I would consult the generated swagger documentation :)

@cbornet
Copy link
Member

cbornet commented Aug 9, 2017

@gzsombor the intent with the links is not to provide HATEOAS / REST level 3. It's just to provide nice-to-have auto-documentation for the humans, not expecting smart clients to use them at runtime.

@Blackdread
Copy link
Contributor

Blackdread commented Aug 11, 2017

Hi,
Not sure this is here (relates more or less to same kind of issue) I should ask but:
With a new project generated I have relationships of ManyToOne and default generated code does not define it as LAZY (even for OneToOne), as a result for DTOs mapper that were generated as well it expects those relationship as being fetched.
Problem it results in N+1 queries for the app for default entities management pages generated by jhipster.
Of course if I change all relationship to LAZY then I get exception as session was closed, so it would require to write manually join fetch in repositories to make that work (takes time, especially when have more than 150 entities).

Is it normal that jHipster does not define all relationship as LAZY?
If could generate as LAZY then why not define in repositories a EntityGraph that fetches this xToOne relationship in order to show these entity management page?

Was this choice to reflect JPA definition of relationships?
But Hibernate (and even high-performance-java-persistence book) recommend to use Lazy everywhere then do join fetch per query basis.

Thank you.

@jdubois
Copy link
Member

jdubois commented Aug 12, 2017

@Blackdread please don't pollute the thread, for general questions please use stackoverflow
(and I don't think JHipster does eager relationships by default anywhere)

@jdubois
Copy link
Member

jdubois commented Aug 31, 2017

Sorry for my previous comment @Blackdread - I see that in fact you are an Hibernate master (in ticket #6105 ) and that I should listen to you more :-)

Anyway: this as been opened for too long, and I'm not sure we can find an easy solution. I just don't have enough time at the moment to work on this - @gzsombor @cbornet you are probably the 2 best experts here, what do you think? Should we close this?

@cbornet
Copy link
Member

cbornet commented Aug 31, 2017

There is really a bug so I don't think we can close this without any fix...

@apovn
Copy link

apovn commented Nov 29, 2017

It's been a long time. I don't know whether this bug is fixed or not.
A solution that worked for me is:
@ManyToMany(fetch = FetchType.EAGER)
@BatchSize(size=100)

Put it in the entity that have ManytoMany relationship.

It will reduce considerably the number of query in case the children entities is too large.

Hope this help.

@jdubois
Copy link
Member

jdubois commented Nov 29, 2017

@apovn no it has not been fixed, the bug is still opened. But nobody works on this...
As written several times in this thread, in particular by @cbornet , doing an Eager fetch is usually a code smell. Maybe it works in your use case, but I agree with @cbornet we shouldn't generate this by default anywhere in our code (which doesn't mean you shouldn't change our default configuration, depending on your business needs)

@apovn
Copy link

apovn commented Nov 30, 2017

I don't know why nobody works on this because it throws an exception if I don't add the code as I mentioned in previous comment.

In my code: Customer and Ticket have ManyToMany relationship.
When I list all Tickets (/api/tickets), it throws Exception below:
Line 74:
image

Do you have a solution for this problem, @jdubois ?

@jdubois
Copy link
Member

jdubois commented Nov 30, 2017

Nobody is working on it because that doesn't seem to interest anyone... People just have better things to do, that's all.
I would have a solution if I had time to work on this: as far as I'm concerned, MapStruct is still marked BETA, and I'm not using it personally, so this is not my priority.

@apovn
Copy link

apovn commented Nov 30, 2017

ok, i understand.
thank you.

@gzsombor
Copy link
Member

The better solution is to fix the transaction handling :

  • either put the mapper code inside the service (which already has @Transactional annotation)
  • or if you insist on not using services, put @Transactional annotation on your rest methods.

Basically, you need to access your database from a code block, which is in a 'JPA/hibernate session'

@deepu105
Copy link
Member

@gzsombor @jdubois what you think of showing DTO and Filter option only when Service is selected? it will atleast solve these kind of issues

@gzsombor
Copy link
Member

Yes, that would make sense !

@jdubois
Copy link
Member

jdubois commented Dec 4, 2017

I like it that we offer the options to have "no DTOs and a service layer", and "no service layer and DTOs". But indeed, it doesn't make much sense to have DTOs without a service layer, and this seems to constantly cause trouble to people.
We should at the very least issue a warning in the question. People should understand why they choose an option, so if you have DTOs but no service layer, well you should be aware you will get lazy initialization errors. And if you select this, then you're big enough to handle with it.
If that's not enough maybe remove the option, OK - but that means this would have impact on the JDL, so maybe that's too much work.

@MathieuAA
Copy link
Member

MathieuAA commented Dec 4, 2017

@jdubois what I can do is issue the warning if the options are "incompatible" at JDL-parsing time.

@deepu105
Copy link
Member

deepu105 commented Dec 4, 2017 via email

@deepu105
Copy link
Member

I have disabled DTO if service is not selected this won't affect existing apps and JDL as currently it only disables the prompt. @MathieuAA it would be nice if we can do the warning from JDL as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests