Spring Boot MongoDB Can't find a codec for class - mongodb

I'm new to MongoDb, I pulled a simple aggregation from compass. Now I am trying to return the data, unfortunately I am getting this error:
Caused by: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class com.example.DemoMongo.model.User.
this is my configuration in spring boot:
Model
#Document("user")
public class User {
#Id
private String id;
private String name;
private List<Indirizzi> indirizzi;
public String getId() {
return id;
}
public String getName() {
return name;
}
public List<Indirizzi> getIndirizzi() {
return indirizzi;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setIndirizzi(List<Indirizzi> indirizzi) {
this.indirizzi = indirizzi;
}
#Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", indirizzi=" + indirizzi + "]";
}
#Document("indirizzi")
public class Indirizzi {
#Id
private String id;
private String via;
public String getId() {
return id;
}
public String getVia() {
return via;
}
public void setId(String id) {
this.id = id;
}
public void setVia(String via) {
this.via = via;
}
#Override
public String toString() {
return "Indirizzi [id=" + id + ", via=" + via + "]";
}
}
Repository
public class UserRepositoryImpl implements UserCustomRepository {
private final MongoTemplate mongoTemplate;
#Autowired
public UserRepositoryImpl(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
#Override
public List<User> getUser() {
MongoCollection<Document> collection = this.mongoTemplate.getCollection("user");
AggregateIterable<User> result = collection.aggregate(Arrays.asList(new Document("$lookup",
new Document("from", "indirizzi")
.append("localField", "indirizzi")
.append("foreignField", "_id")
.append("as", "indirizzi"))),User.class);
List<User> list= new ArrayList<>();
MongoCursor<User> iterator = result.iterator(); //<- ERROR! Can't find a codec for class com.example.DemoMongo.model.User.
while (iterator.hasNext()) {
User user = iterator.next();
list.add(user);
}
return null;
}
}
public interface UserRepository extends MongoRepository<User,String>,UserCustomRepository{
public List<User>getUser();
}
public interface UserCustomRepository {
List<User> getUser();
}
POM dependencies
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Thanks in advance

Related

How to achieve MVVM + Live Data with retofit generic Api call in Android?

I want to create retrofit2 generic Api call in MVVM Architechture. I have not found any proper tutorial regardng this topic. I have done MVVM Architecture successfully . but I want to make Retrofit Api call generic through out the Application .Please help me out.
here is my code Repository
public class MainRepository {
// private List<ContactList> users = new ArrayList<>();
private MutableLiveData<ContactList> mutableLiveData = new MutableLiveData<>();
private Application application;
public MainRepository(Application application) {
this.application = application;
}
public MutableLiveData<ContactList> getMutableLiveData() {
Retrofit retrofit = ApiClient.getClient();
ApiListInterface apiListInterface = retrofit.create(ApiListInterface.class);
Call<ContactList> call = apiListInterface.getContacts();
call.enqueue(new Callback<ContactList>(){
#Override
public void onResponse(Call<ContactList> call, Response<ContactList> response) {
ContactList contactLists = response.body();
if (contactLists != null ) {
// users = (List<ContactList>) contactLists.ge;
mutableLiveData.setValue(contactLists);
}
}
#Override
public void onFailure(Call<ContactList> call, Throwable t) {
Log.d("ListSize"," - > Error "+ t.getMessage());
}
});
return mutableLiveData;
}
}
here is my ViewModel class
public class MainViewModel extends AndroidViewModel {
private MainRepository mainRepository;
public MainViewModel(#NonNull Application application) {
super(application);
mainRepository = new MainRepository(application);
}
public LiveData<ContactList> getAllUsers() {
return mainRepository.getMutableLiveData();
}
}
Here is My all Model class
public class ContactList {
#SerializedName("contacts")
#Expose
private List<Contact> contacts = null;
public List<Contact> getContacts() {
return contacts;
}
public void setContacts(List<Contact> contacts) {
this.contacts = contacts;
}
}
public class Contact {
#SerializedName("id")
#Expose
private String id;
#SerializedName("name")
#Expose
private String name;
#SerializedName("email")
#Expose
private String email;
#SerializedName("address")
#Expose
private String address;
#SerializedName("gender")
#Expose
private String gender;
#SerializedName("phone")
#Expose
private Phone phone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Phone getPhone() {
return phone;
}
public void setPhone(Phone phone) {
this.phone = phone;
}
}
public class Phone {
#SerializedName("mobile")
#Expose
private String mobile;
#SerializedName("home")
#Expose
private String home;
#SerializedName("office")
#Expose
private String office;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
public String getOffice() {
return office;
}
public void setOffice(String office) {
this.office = office;
}
}
Here is My Activity
public class MainActivity extends AppCompatActivity {
private MainViewModel mainViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
getUserList();
}
private void getUserList() {
mainViewModel.getAllUsers().observe(this, new Observer<ContactList>() {
#Override
public void onChanged(ContactList contactLists) {
Log.d("contacts_list",contactLists.getContacts().toString());
}
});
}
}

Postgres DDL error: 'syntax error at or near "user"' [duplicate]

This question already has answers here:
Cannot create a database table named 'user' in PostgreSQL
(5 answers)
Unable to use table named "user" in postgresql hibernate
(6 answers)
Closed 3 years ago.
i am trying to setup spring boot project by using postgres database. my entities are : -
USER
#Entity
public class User implements UserDetails {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id", nullable = false, updatable = false)
private Long id;
private String username;
private String password;
private String firstName;
private String lastName;
#Column(name="email", nullable = false, updatable = false)
private String email;
private String phone;
private boolean enabled=true;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JsonIgnore
private Set<UserRole> userRoles = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorites = new HashSet<>();
userRoles.forEach(ur -> authorites.add(new Authority(ur.getRole().getName())));
return authorites;
}
#Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
}
ROLE
#Entity
public class Role {
#Id
private int roleId;
private String name;
#OneToMany(mappedBy = "role", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private Set<UserRole> userRoles = new HashSet<>();
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
}
USER_ROLE
#Entity
#Table(name="user_role")
public class UserRole {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long userRoleId;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="user_id")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="role_id")
private Role role;
public UserRole(){}
public UserRole(User user, Role role) {
this.user = user;
this.role = role;
}
public Long getUserRoleId() {
return userRoleId;
}
public void setUserRoleId(Long userRoleId) {
this.userRoleId = userRoleId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
and my application.properties file looks like:-
server.port=5060
spring.thymeleaf.cache=false
spring.datasource.url=jdbc:postgresql://localhost:5432/pcms
spring.datasource.data-username=sagar
spring.datasource.password=sagar
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL94Dialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
so whenever i run this application. user_role and role tables are created successfully on postgresql database. but user entity throws an exception.
the error says:-
2018-05-07 15:44:15.847 WARN 23619 --- [ restartedMain] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:440) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:424) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:375) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:166) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:135) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:121) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:155) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:72) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:312) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:460) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892) [hibernate-core-5.2.16.Final.jar:5.2.16.Final]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.0.1.RELEASE.jar:2.0.1.RELEASE]
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "user"
Position: 108
as you can see the error points on USER entity. but the same entity runs fine when the application is connected to mysql database. i could not quite figure out what is the real error behind it.
User is actually a reserved keyword that Spring JPA doesn't "escape" as-is. However, you can do the keyword escape like so in your entity declaration:
#Entity
#Table(name = "\"User\"")
public class User implements UserDetails { ... }
Spring is likely escaping it for you in your MySql database or taking care of it for you in some other way; not the case for your PostgreSQL DB.

Spring Batch:- One reader multiple writers

File structure I have a flat file which has two types of data. such as I have a Comma delimited file that has information of a students. There are multiple files like class A students, class B students etc.
Data in file is like first line has the class information and the rest has student information. So I want to put the class information to class table and student information to student table.
First line would always be of HeaderDataDAO type and all other would be of StudentDataDAO.
How can I achieve this?
My File structure
Class-A*10*2013-14
1*Stone*Barrett*1964-10-19
2*Armando*Stone*1973-02-04****
3*Armando*Logan*1986-12-25
4*Latifah*Barnett*1959-07-24
5*Cassandra*Moses*1956-09-14*********
6*Audra*Hopkins*1984-08-30
7*Upton*Morrow*1973-02-04
8*Melodie*Velasquez*1953-04-26
9*Sybill*Nolan*1951-06-24*****
10*Glenna*Little*1953-08-27
StudentDataDAO.java
public class StudentDataDAO {
private long id;
private String firstName;
private String lastName;
private Date birthDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) throws ParseException {
if (!birthDate.equalsIgnoreCase("")) {
SimpleDateFormat spf = new SimpleDateFormat("yyyy-MM-dd");
this.birthDate = spf.parse(birthDate);
} else {
this.birthDate = null;
}
}
#Override
public String toString() {
return "CustomerData [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", birthDate=" + birthDate
+ "]";
}
}
HeaderDataDAO.java
public class HeaderDataDAO {
private String className;
private String numberOfStudent;
private String batch;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getNumberOfStudent() {
return numberOfStudent;
}
public void setNumberOfStudent(String numberOfStudent) {
this.numberOfStudent = numberOfStudent;
}
public String getBatch() {
return batch;
}
public void setBatch(String batch) {
this.batch = batch;
}
#Override
public String toString() {
return "HeaderData [className=" + className + ", numberOfStudent=" + numberOfStudent + ", batch=" + batch + "]";
}
}
You can use CompositeItemWriter below is sample config
<bean id="compositeWriter"
class="org.springframework.batch.item.support.CompositeItemWriter">
<property name="delegates">
<list>
<ref bean="classWriter" />
<ref bean="studentWriter" />
</list>
</property>
</bean>
Using CompositeItemWriter. Find sample over here: https://github.com/spring-projects/spring-batch/blob/master/spring-batch-samples/src/main/resources/jobs/compositeItemWriterSampleJob.xml
http://grepcode.com/file/repo1.maven.org/maven2/org.springframework.batch/spring-batch-samples/1.0.1.RELEASE/jobs/compositeItemWriterSampleJob.xml

update of an object containing a polymorphic set in MongoDB using SpringBoot

I have a "Fonction" class persisted in my Mongo data base which contain a set of objects extending "ItemAccesFonction" class :
#Document
public class Fonction {
#Id
private String _id;
#Indexed
private String name;
private Set<ItemAccesFonction> access;
public Fonction() {
}
public Fonction(String name, Set<ItemAccesFonction> acces) {
this.name = name;
this.access = acces;
this._id = name;
}
public Fonction(String name) {
this.name = name;
this.access = new HashSet<>();
this._id = name;
}
public String getId() {
return _id;
}
public void setId(String id) {
this._id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<ItemAccesFonction> getAccess() {
return access;
}
public void setAccess(Set<ItemAccesFonction> access) {
this.access = access;
}
}
Here is my "ItemAccesFonction" class and those which extend it :
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_class")
public class ItemAccesFonction {
private String _id;
private String _class;
public ItemAccesFonction() {
this._class = getClass().getCanonicalName();
}
public ItemAccesFonction(final String id) {
this._id = id;
this._class = getClass().getCanonicalName().toString();
}
public String getId() {
return _id;
}
public void setId(final String idItemAcces) {
this._id = idItemAcces;
}
public String get_class() {
return _class;
}
public void set_class(final String _class) {
this._class = _class;
}
}
public class ApplicationFonction extends ItemAccesFonction{
private List<String> listeGroupes;
public ApplicationFonction() {
super();
this.listeGroupes = new ArrayList<String>();
}
public ApplicationFonction(String id, List<String> listeGroupes) {
super(id);
this.listeGroupes = listeGroupes;
}
public List<String> getListeGroupes() {
return listeGroupes;
}
public void setListeGroupes(final List<String> listeGroupes) {
this.listeGroupes = listeGroupes;
}
}
public class RepertoireFonction extends ItemAccesFonction{
private String droitSelection;
public RepertoireFonction() {
super();
}
public RepertoireFonction(String id ,String droitSelection) {
super(id);
this.droitSelection = droitSelection;
}
public String getDroitSelection() {
return droitSelection;
}
public void setDroitSelection(final String droitSelection) {
this.droitSelection = droitSelection;
}
}
I encounter an issue when I try to update a Fonction. I get the following error, but not everytime :
{
"cause": {
"cause": {
"cause": null,
"message": "Target bean of type com.wps.gp.datamongo.model.acces.ItemAccesFonction is not of type of the persistent entity (com.wps.gp.datamongo.model.acces.RepertoireFonction)!"
},
"message": "Could not read payload!; nested exception is java.lang.IllegalArgumentException: Target bean of type com.wps.gp.datamongo.model.acces.ItemAccesFonction is not of type of the persistent entity (com.wps.gp.datamongo.model.acces.RepertoireFonction)!"
},
"message": "Could not read an object of type class com.wps.gp.datamongo.model.Fonction from the request!; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not read payload!; nested exception is java.lang.IllegalArgumentException: Target bean of type com.wps.gp.datamongo.model.acces.ItemAccesFonction is not of type of the persistent entity (com.wps.gp.datamongo.model.acces.RepertoireFonction)!"
}
Does someone have an idea of what I am doing wrong?
Thanks

In spring security 3,how to customize my # PreAuthorize annotation?

these days I meet a problem, I can not figure it out,so please help me...
My entity: Utilisateur this is a french word means user
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class Utilisateur implements Serializable
{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected int id;
protected String login;
protected String password;
protected String nom;
protected String prenom;
protected String email;
protected String username;}
#OneToOne(mappedBy="user", cascade={CascadeType.ALL})
private Role role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return login;
}
public void setUsername(String username) {
this.username = username;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
and a Role entity.
In my web app, there is a controller to show for example the information about a student(Etudiant in french)
#EJB(mappedName = "Etudiant.EtudiantFacade")
EtudiantFacade etudiantF;
// Affiche le detail d'un Etudiant (show the infomations of the student)
#RequestMapping(value = "/Etudiant/{idEtudiant}/info")
public ModelAndView detail(#PathVariable String idEtudiant, Model m) {
m.addAttribute("etudiant",
etudiantF.trouver(Integer.parseInt(idEtudiant)));
return new ModelAndView("EtudiantInformation", "null", null);
}
I implemented my own CustomUseDetailService using the entity Utilisateur directly.
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
// TODO Auto-generated method stub
System.out.println("!!!!!!!!!!!!!!!!!");
System.out.println(username);
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
Utilisateur etudiant = etudiantF.trouverParLogin(username);
return new User(etudiant.getLogin(), etudiant.getPassword(), enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,getAuthorities(etudiant.getRole().getRole()));
}
and my security.xml is below:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/app/Login" access="permitAll"/>
<intercept-url pattern="/app/*" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')"/>
<form-login login-page="/app/Login"
authentication-success-handler-ref="authenticationSuccessHandler"/>
<logout logout-url="/app/Logout" logout-success-url="/"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="customUserDetailsService"/>
</authentication-manager>
Last my question is:
for a student, his id is 1, his username is stu1,to control this student with id 1 can only access his own page information /ProjetName/Student/{studentId}/Info
how do I write the code with #PreAuthorize, I have see the document in form spring, there is example like #PreAuthorize(#contract.name = principal.username), because there is a attribute username in principal, but here,what I need is Id, I use #RequestMapping(value = "/Etudiant/{idEtudiant}/info") to match the student not the username. So how can I solve it? Many thanks... I can not find the tutorial.
You can provide your own implementation for User class (just extend org.springframework.security.core.userdetails.User). Add an identifier field to it. Then set corresponding value in loadUserByUsername method:
#Override
public UserDetails loadUserByUsername(String username)
...
return new CustomUser(etudiant.getId(), etudiant.getLogin(), etudiant.getPassword(), enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,getAuthorities(etudiant.getRole().getRole()));
}
Then you will be able to use it:
#PreAuthorize(#contract.name = principal.id)