Skip to content

Commit

Permalink
Unfetched Attribute exception for embedded entity during editor save…
Browse files Browse the repository at this point in the history
… when having transient property jmix-framework#1383
  • Loading branch information
dtaimanov committed Mar 25, 2023
1 parent 60d3e43 commit dcb31c0
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

import java.util.Collection;
import java.util.List;
import java.util.Set;

@Component("core_PersistentAttributesLoadChecker")
public class CorePersistentAttributesLoadChecker implements PersistentAttributesLoadChecker {
Expand Down Expand Up @@ -66,11 +65,17 @@ public boolean isLoaded(Object entity, String property) {
if (dependsOnProperties.isEmpty()) {
return true;
} else {
for (String relatedProperty : dependsOnProperties) {
if (!isLoaded(entity, relatedProperty))
boolean fullFetchingOfAllPropertiesGuaranteed = true;
for (String relatedPropertyName : dependsOnProperties) {
MetaProperty relatedProperty = metaClass.getProperty(relatedPropertyName);
if (relatedProperty.getRange().isClass()) {
fullFetchingOfAllPropertiesGuaranteed = false;
}
if (!isLoaded(entity, relatedPropertyName))
return false;
}
return true;

return fullFetchingOfAllPropertiesGuaranteed || checkIsLoadedWithGetter(entity, property);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ protected boolean isLoadedSpecificCheck(Object entity, String property, MetaClas
return true;//NoValue placeholder should be considered as loaded like null values of just saved entities
}
} catch (RuntimeException e) {
log.debug("Cannot get value for property {} of class {}", property, entity.getClass().getName());
log.trace("Cannot get value for property {} of class {}", property, entity.getClass().getName());
}

EntityManagerFactory emf = storeAwareLocator.getEntityManagerFactory(metaClass.getStore().getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.apache.commons.lang3.RandomStringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jdbc.core.JdbcTemplate
import test_support.DataSpec
import test_support.entity.entity_extension.Client
import test_support.entity.sales.Order
import test_support.entity.sales.OrderLineA
import test_support.entity.sales.OrderLineB
Expand Down Expand Up @@ -183,4 +184,32 @@ class EntityStatesTest extends DataSpec {
dataManager.remove(Id.of(user))
dataManager.remove(Id.of(group))
}

def "method-based attribute loaded state determined correctly"() {
setup:
var client = dataManager.create(Client);
client.name = "Diego"
client.address.city = "Khorinis"
client.address.street = "Square"
dataManager.save(client)

when:
var loadedClient = dataManager.load(Client)
.id(client.id)
.fetchPlan { fp ->
fp.addAll('name', 'address', "address.street").partial()
}
.one();
then:
!entityStates.isLoaded(loadedClient, "label1")
!entityStates.isLoaded(loadedClient, "label2")
!entityStates.isLoaded(loadedClient, "addressCity")

entityStates.isLoaded(loadedClient, "htmlName")
entityStates.isLoaded(loadedClient, "label3")
entityStates.isLoaded(loadedClient, "addressStreet")

cleanup:
dataManager.remove(client)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2022 Haulmont.
*
* 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 test_support.entity.entity_extension;

import io.jmix.core.entity.annotation.EmbeddedParameters;
import io.jmix.core.entity.annotation.JmixGeneratedValue;
import io.jmix.core.metamodel.annotation.DependsOnProperties;
import io.jmix.core.metamodel.annotation.InstanceName;
import io.jmix.core.metamodel.annotation.JmixEntity;
import io.jmix.core.metamodel.annotation.JmixProperty;

import javax.persistence.*;
import java.util.UUID;

/**
* Entity to check that loaded state of method-based attributes determined correctly
*/
@JmixEntity
@Entity(name = "exttest_Client")
@Table(name = "EXTTEST_CLIENT")
public class Client {

@Id
@Column(name = "ID")
@JmixGeneratedValue
protected UUID id;

@Column(name = "NAME")
@InstanceName
protected String name;

@Embedded
@EmbeddedParameters(nullAllowed = false)
private Address address;


@JmixProperty
@DependsOnProperties({"address", "name"})
public String getLabel1() {
return name + " - " + address.getCity();
}

@JmixProperty
@DependsOnProperties({"name", "address"})
public String getLabel2() {
return name + " - " + address.getCity();
}

@JmixProperty
@DependsOnProperties({"address", "name"})
public String getLabel3() {
return name + " - " + address.getStreet();
}

@JmixProperty
@DependsOnProperties({"address"})
public String getAddressStreet() {
return ">" + address.getStreet() + "<";
}

@JmixProperty
@DependsOnProperties({"address"})
public String getAddressCity() {
return ">" + address.getCity() + "<";
}


@JmixProperty
@DependsOnProperties({"name"})
public String getHtmlName() {
return "</b>" + name + "</b>";
}

public UUID getId() {
return id;
}

public void setId(UUID id) {
this.id = id;
}

public String getName() {
return name;
}

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

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}
}

0 comments on commit dcb31c0

Please sign in to comment.