LookupField with one-to-many relationship - jpa

I want to show in my document a one-to-many relationship- a simple drop-down list with values. For that, I trying to create and configure LookupField component by using Cuba platform.
I have two entities:
CardItem:
#NamePattern("The document in the following state: %s|cardState")
#Table(name = "TKB_CARD_ITEM")
#Entity(name = "tkb$CardItem")
public class CardItem extends StandardEntity {
// skipped
CardType:
#NamePattern("CardType: %s, %s |cardTypeItem, cardTypeName")
#Table(name = "TKB_CARD_TYPE")
#Entity(name = "tkb$CardType")
public class CardType extends StandardEntity {
#OneToMany(targetEntity=CardItem.class )
private List<CardItem> cardItems;
// skipped
In my card-item-edit.xml I have the following:
<dsContext>
<datasource id="CardItemDs" class="com.company.tkb.entity.CardItem" view="_local"/>
<collectionDatasource id="CardTypeDs" class="com.company.tkb.entity.CardType" view="_local">
<query>select c from tkb$CardType c</query>
</collectionDatasource>
</dsContext>
<layout>
<lookupField datasource="CardItemDs" property="cardTypeName" optionsDatasource="CardTypeDs"/>
I filled the table TKB_CARD_TYPE with some values. Now I'm trying to get a drop-down list with values when I create CardItem, but the list is empty.
What could be the problem?
I would be very grateful for the information. Thanks to all.

What helped:
In CardItemEdit class I added the following:
public class CardItemEdit extends AbstractEditor<CardItem> {
#Inject
private Datasource<CardItem> cardItemDs;
#Inject
private Metadata metadata;
#Override
public void init(Map<String, Object> params) {
CardItem cardItem = metadata.create(CardItem.class);
cardItemDs.setItem(cardItem);
}
}
Then I changed the direction of the relationship: part of my CardItem entity:
#NamePattern("The document in the following state: %s|cardState")
#Table(name = "TKB_CARD_ITEM")
#Entity(name = "tkb$CardItem")
public class CardItem extends StandardEntity {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "CARD_TYPE_ID")
protected CardType cardType;
// skipped
Part of my CardType entity:
#NamePattern("Тип входящего документа: %s | cardTypeName")
#Table(name = "TKB_CARD_TYPE")
#Entity(name = "tkb$CardType")
public class CardType extends StandardEntity {
// skipped
I defined the dsContext and lookupField by this way:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
caption="msg://editCaption"
class="com.tkbbank.client.web.item.CardItemEdit"
datasource="cardItemDs"
focusComponent="fieldGroup"
messagesPack="com.tkbbank.client.web.item">
<dsContext>
<datasource id="cardItemDs" class="com.tkbbank.client.entity.CardItem" allowCommit="false"/>
<collectionDatasource id="cardTypeDs" class="com.tkbbank.client.entity.CardType" view="_local">
<query>
<![CDATA[select e from demo$CardType e]]>
</query>
</collectionDatasource>
</dsContext>
<dialogMode forceDialog="true" width="AUTO"/>
<layout expand="windowActions" spacing="true">
<fieldGroup id="fieldGroup" datasource="cardItemDs">
<column width="500px">
<field id="cardCreationDate" editable="false"/>
<field id="cardType" caption="Тип документа">
<lookupField datasource="cardItemDs" property="cardType" optionsDatasource="cardTypeDs"/>
</field>
<field id="cardSubtype"/>
<field id="cardAutoFill"/>
<field id="cardOutcomeNumber"/>
<field id="cardDate"/>
<field id="cardOrganization"/>
<field id="cardDeliveryMethod"/>
<field id="cardAdditionalInformation"/>
<field id="registratorName"/>
</column>
</fieldGroup>
<frame id="windowActions" screen="editWindowActions"/>
</layout>
</window>
What I see now. My card:
Interface for populating CardType with data:
Interface viewing all the documents:
Now everything is ok.
By side: very helpfull questions about "Can’t find getter for property" exception(this error is appeared also):
Hibernate - PropertyNotFoundException: Could not find a getter for
“ Could not find a getter for ” Error
What is the purpose of AccessType.FIELD, AccessType.PROPERTY and #Access
IllegalArgumentException: Can’t find getter for property ” at class…, and forgetting to update #NamePattern

Related

Get attributes in view from inherited objet

In one of my jsf view I'm displaying a list of users with some information like : CardId (child), Firstname (parent), Lastname (parent).
Only the attributes from the child class are displayed.
The class User contain the Firsname and Lastname and the child a new attribute cardId.
<h:selectOneMenu>
<f:selectItem itemLabel="Looking into my pocket ..." />
<f:selectItems value="#{PresentationBean.getReaders()}" var="reader" itemLabel="#{reader.cardId} (#{reader.firstname}-#{reader.lastname})" itemValue="#{reader.cardId}" />
</h:selectOneMenu>
Child class
#Entity
public class Reader extends User {
private int cardId;
//some code
}
Parent class
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Entity
public abstract class User {
private String firstname, lastname;
//some code
}
As result my dropdown only display the CardId
The log also state that all the field are queried.
20:36:26,627 INFO [stdout] (default task-26) Hibernate: select reader0_.email as email2_4_, reader0_.city as city3_4_, reader0_.street as street4_4_, reader0_.zipCode as zipCode5_4_, reader0_.firstname as firstnam6_4_, reader0_.lastname as lastname7_4_, reader0_.accountBalance as accountB8_4_, reader0_.cardId as cardId9_4_ from User reader0_ where reader0_.DTYPE='Reader'

Exclude Models or properties from swagger response

I used swagger in my apache cxf project , used #Api and #ApiOperations and #ApiParam annotations and generated a api doc for the rest services.
But I want to exclude some of the fields like EntityTag, StatusType and MediaType etc from Models attribute or complete modules or properties attribute.
How to do that?
I was fetching data from db and setting it to user object and passing that user object to JAX-RS response builder.
Below is one of my DTO Object:
#ApiModel
public class User{
private String name;
private String email;
#ApiModelProperty(position = 1, required = true, notes = "used to display user name")
public int getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
#ApiModelProperty(position = 2, required = true, notes = "used to display user email")
public int getEmail() {
return email;
}
public void setEmail(String email) {
this.email= email;
}
Now I don't see the User object fields or properties inside the Swagger returned json format.
my service class method response is :
#GET
#ApiOperation(value = "xxx", httpMethod = "GET", notes = "user details", response = Response.class)
public Response getUserInfo(){
User userdto = userdaoimpl.getUserDetails();
ResponseBuilder builder = Response.ok(user, Status.OK), MediaType.APPLICATION_JSON);
builder.build();
}
<bean id="swaggerConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="com.services.impl" />
<property name="version" value="1.0.0" />
<property name="basePath" value="http://localhost:8080/api" />
<property name="license" value="Apache 2.0 License" />
<property name="licenseUrl"
value="http://www.apache.org/licenses/LICENSE-2.0.html" />
<property name="scan" value="true" />
</bean>
First of all, you should upgrade to the latest swagger-core version, currently 1.3.12 (you're using a really old one).
You have 3 ways to hide a property:
If you're using JAXB annotations, you can use #XmlTransient.
If you're using Jackson, you can use #JsonIgnore.
If you're not using either, or don't want to affect the general de/serialization of your models, you can use Swagger's #ApiModelProperty's hidden attribute.
Keep in mind you may need to set these on your getters/setters rather than on the property itself. Play with the definitions to see what works for you.
With regards to the issue with the User model, the problem is that you do not reference it from the #ApiOperation (you also don't need the httpMethod property). Try changing it as follows:
#ApiOperation(value = "xxx", notes = "user details", response = User.class)
You can exclude fields like that :
#ApiModelProperty(position = 1, required = true, hidden=true, notes = "used to display user name")

Object of type 'System.String' cannot be converted to type 'MongoDB.Bson.ObjectId'

I have a C# class which has an id field of type ObjectId:
[BsonId]
[SolrUniqueKey("id")]
public ObjectId Id { get; set; }
In Solr, the schema has defined id as:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
When attempting to pull an object from Solr it fails because it can't cast the string id to MongoDB ObjectId. Does anyone an easy was of fixing this without changing the source for SolrNet?
For anyone interested, below is how I ended-up doing it without modifying SolrNet source code.
I've added an additional property in the class called IdAsString and set it as "BsonIgnore" so that it doesn't get stored in MongoDB, however I use that field to map it to Solr's id field:
[BsonId]
public ObjectId Id { get; set; }
[BsonIgnore]
[SolrUniqueKey("id")]
public string IdAsString
{
get { return Id.ToString(); }
set { Id = ObjectId.Parse(value); }
}

How can I create bi-directional mappings with MyBatis 3.0.5?

Say I have two domain objects and a mapper interface.
class Person {
int id;
List<Problem> problems = new ArrayList<Problem>();
}
class Problem {
int id;
Person person;
}
interface PersonMapper {
public List<Person> selectAllPersons();
}
And two database tables.
create table person (
id integer not null generated always as identity constraint person_pk primary key,
)
create table problem (
id integer not null generated always as identity constraint problem_pk primary key,
person_id integer not null constraint problem_person_fk references person
)
I can create a mapping file that gets the data I want.
<resultMap id="personMap" type="Person">
<id column="person_id" property="id" />
<collection column="problem_person_id" property="problems"
javaType="ArrayList" ofType="Problem" resultMap="problemMap" />
</resultMap>
<resultMap id="problemMap" type="Problem">
<id column="problem_id" property="id" />
<!-- Adding an association here will cause a circular dependency -->
<!-- The circular dependency results in a StackOverflowException -->
</resultMap>
<select id="selectAllPersons" resultMap="personMap">
select
person.id as person_id,
problem.id as problem_id
from person left outer join problem on person.id = problem.person_id
</select>
However, since MyBatis doesn't do bi-directional mapping, none of the Problem objects in the returned collections will have their Person reference set correctly.
According to this issue, it sounds like I should be able to update my mapper interface and add a custom result handler that can be supplied by the calling class.
interface PersonMapper {
public List<Person> selectAllPersons(ResultHandler handler);
}
class PersonResultHandler implements ResultHandler {
#Override
public void handleResult(ResultContext context) {
System.out.println(context.getResultObject());
}
}
class PersonDAO {
// Get SqlSession sqlSession
sqlSession.getMapper(PersonMapper.class).selectAllPersons(new PersonResultHandler());
}
However, the handleResult method of my ResultHandler never gets called. I've seen this example, but the extra fluff class in there makes it very difficult to understand. Can anyone give me a simple example of using a custom ResultHandler with mapper interfaces? I'm using MyBatis 3.0.5+.
I've also read through the MyBatis mailing list and there are several suggestions of using caching and lazy loading to solve circular dependencies, but I can't find any examples of how to do it.
You should replace your method declaration to:
interface PersonMapper {
public void selectAllPersons(ResultHandler handler);
}
And populate List<Person> inside your PersonResultHandler
class PersonResultHandler implements ResultHandler {
List<Person> persons = new ArrayList<Person>();
#Override
public void handleResult(ResultContext context) {
Object result = context.getResultObject();
if (result instanceof Person) {
Person person = (Person) result;
for (Problem problem : person.getProblems()) {
problem.setPerson(person);
}
persons.add(person);
}
}
public List<Person> getPersons() {
return persons;
}
}

nhibernate: how to map two tables to a single non-persistent class?

I have two similar tables:
Table1:
[ id ] | [ name ]
Table2:
[ id ] | [ name ]
and I need to read/write data using only one class:
public class TwinTable
{
public virtual int Id { get; set; }
public virtual string Name1 { get; set; }
public virtual string Name2 { get; set; }
}
Plus one of the tables may or may not have an entity with the specified Id, and both tables may or may not have entities, so Name1 can be null and Name2 can be null and both of them can be null.
I can not change the structure of the DB, and it's not a good thing if i have to add something to it.
Hope for your help!
One solution is to map Table1 to a class, and then map Table2 as a joined-subclass of Table1. The joined subclass will then be like your TwinTable as you described above:
<class name="Class1" table="Table1" >
<id name="Id" column="id">
<generator class="identity" />
</id>
<property name="Name1" column="name" not-null="true" />
</class>
<joined-subclass name="Class2" table="Table2">
<key column="Id" />
<property name="Name2" column="name" not-null="true" />
</joined-subclass>