FileDescriptor in Jmix 2.0

Hi,
Me again :slightly_smiling_face:

In my Cuba application I have this situation:

@JoinTable(name = "PASAPORT_IMAGES_FILE_DESCRIPTOR_LINK",
        joinColumns = @JoinColumn(name = "PASAPORT_ID"),
        inverseJoinColumns = @JoinColumn(name = "FILE_DESCRIPTO_ID"))
@ManyToMany
private List<FileDescriptor> probeImages;

so I need to add many image files to many probes from Pasaport entity.

in Cuba exist FileDescriptor class and entity with table database sys_file.

In Jmix 2.0 exist something like that?

If not exist, is a good idea to take the class for FileDescriptor and TenantEntity from Cuba, and to add at my Jmix application?

Thank you!

Hello,

You can use the old FileDescriptor. More information about migration:

Docs:
https://docs.jmix.io/1.x/jmix/1.1/cuba/index.html#file-storage-migration

Forum:

Regards,
Nikita

Hi Nikita,
Thank you for your answer!

I try it to do first idea but when I saw how many classes dependence exist in behind I stopped.

But I do something like that:

  1. I created an entity SysFile:
/**
 * Copyright 2023 Florin Tanasă
 * *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * *
 * http://www.apache.org/licenses/LICENSE-2.0
 * *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

package com.genebank.genedatabank.entity;

import io.jmix.core.FileRef;
import io.jmix.core.annotation.DeletedBy;
import io.jmix.core.annotation.DeletedDate;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.metamodel.annotation.InstanceName;
import io.jmix.core.metamodel.annotation.JmixEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.OffsetDateTime;
import java.util.Date;
import java.util.Set;
import java.util.UUID;

/**
 * @author : Florin Tanasă
 * @since : 03.10.2023
 **/

@JmixEntity
@Table(name = "SYS_FILE")
@Entity
public class SysFile {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "VERSION", nullable = false)
    @Version
    private Integer version;

    @CreatedBy
    @Column(name = "CREATED_BY")
    private String createdBy;

    @CreatedDate
    @Column(name = "CREATED_DATE")
    private OffsetDateTime createdDate;

    @LastModifiedBy
    @Column(name = "LAST_MODIFIED_BY")
    private String lastModifiedBy;

    @LastModifiedDate
    @Column(name = "LAST_MODIFIED_DATE")
    private OffsetDateTime lastModifiedDate;

    @DeletedBy
    @Column(name = "DELETED_BY")
    private String deletedBy;

    @DeletedDate
    @Column(name = "DELETED_DATE")
    private OffsetDateTime deletedDate;

    @InstanceName
    @Column(name = "NAME", nullable = false, length = 500)
    @NotNull
    private String name;

    @Column(name = "EXT", length = 20)
    private String extension;

    @Column(name = "FILE_SIZE")
    private Long size;

    @Column(name = "CREATE_DATE")
    @Temporal(TemporalType.DATE)
    private Date createDate;

    @NotNull
    @Lob
    @Column(name = "FILE_", nullable = false)
    private FileRef file;

    @JoinTable(name = "PASAPORT_SYS_FILE_LINK",
            joinColumns = @JoinColumn(name = "SYS_FILE_ID", referencedColumnName = "ID"),
            inverseJoinColumns = @JoinColumn(name = "PASAPORT_ID", referencedColumnName = "ID"))
    @ManyToMany
    private Set<Pasaport> pasaports_sysfile;

    public Set<Pasaport> getPasaports_sysfile() {
        return pasaports_sysfile;
    }

    public void setPasaports_sysfile(Set<Pasaport> pasaports_sysfile) {
        this.pasaports_sysfile = pasaports_sysfile;
    }

    public FileRef getFile() {
        return file;
    }

    public void setFile(FileRef file) {
        this.file = file;
    }

    /**
     * @return file uploading timestamp
     */
    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    /**
     * @return file name including extension
     */
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    /**
     * @return file extension, i.e. the part of name after the last dot
     */
    public void setExtension(String extension) {
        this.extension = extension;
    }


    public String getExtension() {
        return extension;
    }

    /**
     * @return file size in bytes
     */
    public Long getSize() {
        return size;
    }

    public void setSize(Long size) {
        this.size = size;
    }


    public OffsetDateTime getDeletedDate() {
        return deletedDate;
    }

    public void setDeletedDate(OffsetDateTime deletedDate) {
        this.deletedDate = deletedDate;
    }

    public String getDeletedBy() {
        return deletedBy;
    }

    public void setDeletedBy(String deletedBy) {
        this.deletedBy = deletedBy;
    }

    public OffsetDateTime getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(OffsetDateTime lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public OffsetDateTime getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(OffsetDateTime createdDate) {
        this.createdDate = createdDate;
    }

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }
}
  1. I create a relation many to many from my Pasaport entity:
...
    @JoinTable(name = "PASAPORT_SYS_FILE_LINK",
            joinColumns = @JoinColumn(name = "PASAPORT_ID", referencedColumnName = "ID"),
            inverseJoinColumns = @JoinColumn(name = "SYS_FILE_ID", referencedColumnName = "ID"))
    @ManyToMany
    private List<SysFile> probeImages;
...
  1. In pasaport-detail-view.xml I add an dataGrid and a image components:
...
 <tab id="probeImages" label="msg://probeImages.label">
                        <vbox id="contentHbox" width="100%" height="100%">
                            <hbox height="100%" width="100%">
                                <vbox width="100%" height="100%">
                                    <hbox id="buttonsPanel4" classNames="buttons-panel">
                                        <button action="probeImagesDataGrid.add"/>
                                        <button action="probeImagesDataGrid.exclude"/>
                                    </hbox>
                                    <dataGrid id="probeImagesDataGrid" dataContainer="probeImagesDc" width="100%">
                                        <actions>
                                            <action id="add" type="list_add"/>
                                            <action id="exclude" type="list_exclude"/>
                                        </actions>
                                        <columns>
                                            <column property="version"/>
                                            <column property="createdBy"/>
                                            <column property="createdDate"/>
                                            <column property="lastModifiedBy"/>
                                            <column property="lastModifiedDate"/>
                                            <column property="deletedBy"/>
                                            <column property="deletedDate"/>
                                            <column property="name"/>
                                            <column property="extension"/>
                                            <column property="size"/>
                                            <column property="createDate"/>
                                            <column property="file"/>
                                        </columns>
                                    </dataGrid>
                                </vbox>
                                <hbox id="probeImageWrapperLayout"
                                      width="100%" height="100%">
                                    <image id="imageProbe" dataContainer="probeImagesDc" property="file"/>
                                </hbox>
                            </hbox>
                        </vbox>
                    </tab>
...
  1. In PasaportDetailView class I add a even when I select a item in dataGrid to see image from the file:
...
    @Subscribe("probeImagesDataGrid")
    public void onProbeImagesDataGridItemClick(final ItemClickEvent<SysFile> event) {
        FileRef fileRef = event.getItem().getFile();
        if (fileRef != null) {
            StreamResource streamResource = new StreamResource(fileRef.getFileName(),
                    () -> fileStorage.openStream(fileRef));
            imageProbe.setVisible(true);
            imageProbe.setSrc(streamResource);
        }
        else imageProbe.setVisible(false);
    }
...

and the result is:

image

Now is necessary to write some code in SysFileDetailView class and the view when I upload a file to determine: extension, filename and the size of file.

I try to use this SysFile entity when I need to works with files.
Is not perfect, but is a solution for the moment.

Complete code at GitHub - florintanasa/genedatabank: GeneDataBank is an genetic plant database.

Cheers,

1 Like