0

First of all I know that there are several threads with solutions but I don't understand them and they do not seem to help me at all. I know where the problem is. Fetching lazy because the session is closed. I thought @Transactional would help but it does not. And I know that I should not use the annotation in the controller. I will change that when I've fixed this problem. And I also will create a DTO instead of annotate the entity.

I got my entity MlpConfig and I want to send alle configs to my frontend. But the connections with other entities make this problems:

Could not write JSON: could not initialize proxy [com.project.data.ActivationFunction#4] - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not initialize proxy...

I need all informations (ActivationFunction, Layers) in the response and I really don't want to fetch EAGER. Even though I set it to EAGER in MlpConfig, ActivationFunction will complain about the same problem (cause of the connection to MlpConfig)

The entity MlpConfig (with @JsonIgnore on all foreign objects the response works):

@Entity
@Data
@NoArgsConstructor
public class MlpConfig {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @NotBlank(message = "Name for the MlpConfig is required")
    @Column(name = "name", nullable = false, length = 255)
    private String name;

    private String description;

    @NotNull(message = "Batch Size is required")
    private int batchSize;

    @NotNull(message = "Epoch Number is required")
    private int epochNumber;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    private ActivationFunction activationFunction;

    @JsonIgnore
    @OneToMany(mappedBy = "mlpConfig", orphanRemoval = true)
    private Set<Layer> layers = new HashSet<>();

    @JsonIgnore
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    private User user;

    private Timestamp lastUpdated;

    public MlpConfig(String name, String description, int batchSize, int epochs, Set<Layer> layers,
            ActivationFunction activationFunction, User user) {
        this.name = name;
        this.description = description;
        this.batchSize = batchSize;
        this.epochNumber = epochs;
        this.activationFunction = activationFunction;
        this.layers = layers;
        this.lastUpdated = Timestamp.from(Instant.now());
        this.user = user;
    }

The call of the method:

@Transactional
@GetMapping("/getAllConfigs")
public ResponseEntity<Object> getAllMlpConfig(@RequestHeader HttpHeaders headers, Authentication authentication) {
    User user = userService.findByUsername(authentication.getName());
    List<MlpConfig> configs = mlpConfigService.findAllByUser_id(user.getId());

    return ResponseEntity.status(HttpStatus.OK).body(configs);
}

The entity ActivationFunction:

@Entity
@Data
@NoArgsConstructor
@Table(name = "activationFunctions")
public class ActivationFunction {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Enumerated(EnumType.STRING)
    @Column(length = 20)
    private EActivationFunction type;

    @ToString.Exclude
    @OneToMany(mappedBy = "activationFunction")
    private Set<MlpConfig> mlpConfig;

    public ActivationFunction(EActivationFunction type) {
        this.type = type;
    }
}

So how to handle this? I just found this one solution for Spring MVC with seems very old.

CptDayDreamer
  • 1,526
  • 6
  • 25
  • 61

1 Answers1

1

I could actually fix this after a whole day.

According to a comment at this answer https://stackoverflow.com/a/37840526/10565504:

For Gradle I added this line to my build.gradle

compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5', version: '2.11.0'

And to get it work I've added:

@Bean
public Module datatypeHibernateModule() {
    return new Hibernate5Module();
}

Afterwards I had to problem that I had an infinite recursion in my code. I could fix it with the following answer: https://stackoverflow.com/a/18288939/10565504

And another problem was that I've used the @ToString.Exclude annotation on my field activationFunction in the MlpConfig entity. The incoming value was always null without toString.

//@EqualsAndHashCode.Exclude
//@ToString.Exclude
@ManyToOne(fetch = FetchType.LAZY)
private ActivationFunction activationFunction;
CptDayDreamer
  • 1,526
  • 6
  • 25
  • 61