FileDescriptor in Jmix 2.0

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:

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. · GitHub

Cheers,

1 Like