Create Document in Different Database - xpages

I am XPagifying an existing Notes Client Application. All the design elements for the XPages part are in a separate database and I am referencing the old database in my data source settings like this:
"servername!!database path and name".
I have one XPage that is being used to create new documents, which are going to be stored in the old database.
However, when I am saving the document, it is not being created and saved in the old database, but in the new database, even though the data source is pointing to the old database.
What does make it work though, is, when I add a databaseName parameter to the URL that opens the XPage, which looks then something like this:
https:// servername/database.nsf/xCreatDocument.xsp?databaseName=targetservername!!targetdatabase.nsf
Do I have to add this to the URL or is there another way to force my XPage to create the document in the other database?
Any help is highly appreciated.
Update 1: 04/06
It seems that the URL has to either contain the parameter "databaseName" as mentioned before or it needs to look like this:
https:// servername/database.nsf/xCreatDocument.xsp?action=newDocument
Then the document will be stored in the target database. I am not sure that there is another way to do it. It seems your URL has to have either one of the URL parameters.

Check your datasource. It should be set something like this.
<xp:this.data>
<xp:dominoDocument var="document1" formName="myform"
databaseName="myserver/mydomain!!mydb.nsf">
</xp:dominoDocument>
</xp:this.data>

If you set the dataSource property ignoreRequestParameters to true then the code you create will override the default behaviors. But then the action=NewDocument will also be meaningless, unless you test for it in the dataSource.action ssjs code.

Related

Keep design element in template database only

Is there a way to keep a design element (e.g View, Form, Agent...) in the template database and not refresh it to the inheritance database when I refresh design?
I have some views I want to delete from a database but keep them on the database template. I don't want them to "return" to the database after refresh design
Thanks,
Y
There is no way to prevent design elements from being inherited. I usually use another solution: Versioning.
Create a new copy of your template and give it another version in Title, Filename and Template name. Then remove the views from this new version and replace design of your database. That way you still have an "old" copy in the older template version.
The other advantage is: If something really goes wrong, you can switch back to the "older" version of the template at any time...

Can replication\save conflicts be identified in Xpages

If I know a notes document opened in Xpages has created a replication\save conflict duplicate document and then search for the document ID in Xpages then both (or all) the documents are shown in an Xpage set up with a specific Notes view in my application. But is there any way I can tell which one is the parent document and which one(s) are the replication response documents? I need to be able to see this on the Xpages front end and not just in the Notes database backend.
If you create a view with #IsAvailable($Conflict) as the selection formula, you can identify conflicts. They have a $REF field which maps to the parent document.
Because XPages allows us to have multiple datasources on an XPage, it should be feasible to open the conflict have dominoDocument datasources for the conflict and the parent document (the non-conflict).
If your view has the option 'Show response documents in a hierarchy' then your parent document comes always first and right after it all the replication conflicts. You can show the replication conflicts this way:
<xp:viewPanel
value="#{view1}"
id="viewPanel1"
var="rowData">
...
<xp:viewColumn
columnName="yourColumnName"
id="viewColumn2"
value="#{javascript:
if (rowData.getDocument().hasItem('$Conflict')) {
var parentId = rowData.getDocument().getItemValue('$REF');
return '[Replication ot Save Conflict]';
}
return rowData.getColumnValue('yourColumnName')
}">
<xp:this.facets>
<xp:viewColumnHeader
value="Unid"
xp:key="header"
id="viewColumnHeader2">
</xp:viewColumnHeader>
</xp:this.facets>
</xp:viewColumn>
</xp:viewPanel>
Orphan replication conflict documents with deleted parent document don't show up in this kind of view.
If your view has not the option 'Show response documents in a hierarchy' set then all replication conflicts would be visible even the orphans. Documents are sorted by the column values so the replication conflicts wouldn't be necessary right beneath the parents document. In this case you might want to show the parent's DocumentUniqueID in addition with the help of parentId variable.
Although previous answers will help, they complicate everything at page level. Get rid of conflicts in their source - so XPage or background code doesn't need to.
In our applications every view used for XPages has selection formula enriched with
& !#IsAvailable( $Conflict )
That way no matter what code (datasource, component, SSJS, Java, #Formula) in XPage does not need to handle conflicts.
Edited to answer your question:
In adition to above, you can have special view with conflicts only (selection of #isAvailable( $Conflict )) sorted by #Text( $REF ) column. You are not able to show any other data for conflict documents.
Then, you can add column that will lookup whether document with specific UNID has any conflict documents and highlight them, show conflict count, or something else.
My two cents though - conflict resolving in Notes client is much clever idea.
All these responses are great but in the end why are conflicts getting generated? There should be logic in the design so that a minimal group of people can edit a document at any one time. If all your users are editor level then re-think your application. Most users should be author access and the use of authors field defines who can edit that document, which might change depending on the workflow status.

Orchard Content Parts that Don't Store Information in the Database

I'm trying to create a content part in Orchard that will perform a request to a web server and display the results of the request. The problem I'm running into is that my part requires no user input and thus I have left the part and part record classes empty. I have a Migrations.cs file that adds a description to the part and makes it attachable as well as creates a content item with the part attached to it. When I go to create a new instance of my content type it tries writing to the database and fails. How do you create a content part in orchard that doesn't try to save to the database? Thank you.
The actual error I receive is:
null id in Orchard.ContentManagement.Records.ContentTypeRecord
I'm pretty sure you don't need to create new table since there are many parts which don't have any in Orchard. Try to remove MyCustomPartRecord.cs and change MyCustomPart.cs
public class MyCustomPart : ContentPart<MyCustomPartRecord>
to
public class MyCustomPart : ContentPart
Then just add driver and view and you should be good without extra tables ... In theory :D
The answer to my problem is even when your part ins't actually saving anything in the database you still need to include a table for the part so it can store the id. I just added the following to my Migrations.cs file and it fixed the problem.
SchemaBuilder.CreateTable("MyCustomPartRecord",
table => table
.ContentPartRecord()
);

Dynamic field binding inside a repeat control

I have a strange thing, I'm using dynamic field binding in a custom control.
The field binding is created like this.
XPage (Datasource "document" is placed here)
Custom Control (String passed in)
(to get errors if there are any)
Repeat (CompositeData is passed to a bean that returns the strings for Rows,columns)
Repeat (repeat 1 variable used for Columns)
Custom Control (fieldname is passed in)
field binding is done like this
#{document[compositeData.fieldName]}
The problem is that when I save the XPage I get an error in the messages control
Document has been saved by another user - Save created a new document as a response to that modified document.
And all fields are cleared.
Any ideas how to debug this or is there something I'm missing?
The "Document has been saved by another user" error is only tip of the iceberg - there are some really strange problems with reapeats that repeats fields that are bound and repeatControls property is set to false. The decoding part of xpages lifecycle cannot handle it properly - the controls will be losing data. You should use repeatControls set to true as Martin suggests.
"Repeat control variable doesn't exists" is probably caused by the property that removes repeats set to true. You can solve this by either changing it to false or by adding additional data context that will keep repeated value.
And finally for this to have add/remove functionality You can use Dynamic Content Control and show(null) hack to rebuild the repeat content.
To manage this complexity better I would advise You to stop using document data source and start creating some managed beans.
If You will follow my suggestions I guarantee that You will get the functionality You are looking for as I have few apps that works great and have this kind of complex data editors in them.
I don't know if it'll help you, but I pass both the document datasource and the field name as parameters to a DynamicField control, and use it like this:
compositeData.dataSource[compositeData.fieldName]
The type of the datasource is com.ibm.xsp.model.DataSource, it's listed as dataInterface under Data Sources.
Do you have repeatControls="true" set for the repeat control?
It sounds like you've got the datasource defined multiple times on the XPage (plus custom controls). Either that or the save button has save="true" but the code saves the document back-end, or code in multiple places saves the same document. I've used the same method of passing the datasource down to the custom control, but that may just be because that was what I saw on a blog.

Orchard CMS - How to manage new fields for custom module widget with database?

I've been working with a custom module that has a widget with some fields stored in the DB. I added a new non-required field to the widget and a corresponding field in the database is not being added. What's the best way to handle this type of change?
I can manually add a field in the dev database to match it, but this is unrealistic for 50 some odd production tenant sites.
To expand on #Bertand's answer a little, you don’t need to create database columns when you add fields (Boolean Field, Text Field, Media Picker Field etc) to content parts because the database structure for storing fields is already in place in the database.
Fields are stored as serialized XML against the content part. All of my records are stored in the Orchard_Framework_ContentItemVersionRecord table (there’s a similar table Orchard_Framework_ContentItemRecord, but that doesn’t appear to be used.
The XML is essentially of the format:
<Data>
<SomePart>
<SomeFieldName SomeFieldProperty=”value”
SomeOtherProperty=”value”>FieldValue</SomeFieldName>
</SomePart>
<SomeOtherPart>
<SomeOtherFieldName>FieldValue</SomeOtherFieldName>
</SomeOtherPart>
</Data>
So, for example you might have something like this:
<Data>
<PicturePart>
<picture AlternateText="" Class="" Style="" Alignment="" Width="1219"
Height="709">~/Media/Default/images/greatPicture.jpg</picture>
</PicturePart>
<PictureType>
<ExtraDescription>It’s a great picture!</ExtraDescription>
</Pictureype>
</Data>
Orchard uses the information from the Settings_XXXRecord tables to determine the types of the fields when it’s deserializing them back from the database.
All of this is why, as Bertand says here, fields are easier to create, but harder to query.
Looking at the solution you've posted, it looks like you're adding custom columns, rather than Orchard Fields. If this is what you're trying to do, then it seems like something you should be doing in a datamigration for your module by using AddColumn, as described here. This would look something like:
public int UpdateFrom1() {
SchemaBuilder.AlterTable("TABLE_NAME", table => table
.AddColumn<int>("mynewcolumn")
.AddColumn<string>("mynewcolumn2")
);
return 2;
}
I'm not sure if it's the ideal solution, but running an sql script that manually adds the columns to the module table for all tenants sites seems to do the trick okay. Luckily I setup all my sites to exist in the same database!
SELECT 'Alter table ' + TABLE_NAME + ' Add mynewcolumn int null,
mynewcolumn2 nvarchar(15) null' FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_NAME LIKE '%the_suffix_my_module_puts_for_a_tenant'
A field is not supposed to add a column in the database. By design.

Resources