Liferay 7.3 - Auto upgrade of custom services - liferay

I have a custom service module (myproject-service & myproject-api).
With Liferay 7.2 and previous versions, when I changed my database model (for exemple : add a new column in a table in the service.xml), I used an UpgradeProcess and an UpgradeStepRegistrator, with an incrementation of the Liferay-Require-SchemaVersion.
Since the 7.3 version, the autoupgrade has been moved to a property and changed to false value. In developpement, this value is true and everything works fine but in production, my custom service doesn't upgrade now at server start.
Is there a solution to make this system works again automatically ? I've seen that now we have to do the upgrade manually in the gogo shell with upgrade:execute command.

You are probably looking for
Set this to true to execute the upgrade process when the portal starts and modules are activated.
upgrade.database.auto.run=false
You still need to build the "upgradeProcess", as in:
https://help.liferay.com/hc/en-us/articles/360018162851-Creating-Data-Upgrade-Processes-for-Modules-

Technically, you could activate the same property in production systems. However, this is neither safe, nor performant: The solution for table updates is generic and (as far as I know) will
export your table's data,
DROP TABLE,
CREATE TABLE (with the new structure)
populate the table with the previously saved data.
Now, apart from this being horribly slow for large amounts of data, there are some other shortcomings:
if you have renamed a column, or
added a non-nullable column,
this would fail to do the work as you expected it (even in development).
Further:
If this process is interrupted at any time, you might lose all of your data
In many cases, a simple ALTER TABLE xxx ADD COLUMN yyy would be sufficient, and is quick, safe and easy to do within SQL. That's where your UpgradeProcess kicks in. You wouldn't want to do that after every little bit in development (hence the property), but you certainly don't want to DROP TABLE with important data in production, and wait for who-knows-how-long, when there was just a trivial change.
From that point of view: You want to write a custom UpgradeProcess, even if you don't know that you do. And there's even a great starting point, that takes away the repetitive and low level work.

Related

using PXDatabase.Delete to remove all row in a Custom table

I am trying to use PXDatabase.Delete to remove specific row(s) in a Custom table or even just to get it to fire off. Here is the code that I am trying to get running:
PXDatabase.Delete<SSINHoldRule>(
new PXDataFieldRestrict<SSINHoldRule.inventoryID>(18));
When I watch SQL profiler for this code to get executed, nothing shows up in the SQL profiler which means that this code is not hitting the database. I have different variations of the above code but to avail. Any help would be appreciated. I am running this code via the TestSDK.
Generally, this would be considered direct DB manipulation, which is frowned upon by Acumatica (Documented within Acumatica certification guidelines) and should be used as a last resort. Is there a reason this is not working with general DAC record manipulation? We want to assess using that before considering a more brute force methods such as PXDatabase.Delete.

Changing creation time for a product

I need to change creation time of a product for my custom logic in my project for the PLP.Is it fine to alter the creation time for a product,via ImpEx?Is it recommended or can it break something else?
Creation Time is initial=true, which means it can be set only once, and only during creation. It can't be edited after that. This value is automatically set by Hybris, and I wouldn't recommend changing it.
Yes you can change it if you use forceWrite=true and use the legacy import mode (it only uses the Jalo layer).
Cf. https://help.hybris.com/1808/hcd/8bef094d86691014a87a93789935b39b.html
However this should only be used for testing purpose. In your project you'll prefer creating a custom attribute to store your own "creation date" if you absolutely need to have logic on this info.
Also, to answer your question, modifying the creation date may impact the cache management. And if you force inconsistent values (creation in the futur or after the modification date for example) you can expect weird results.
Yes, it's not recommended to change it and neither you can change with any modifiers or ImpEx. Still, if you need to change, you can use SQL query to update it directly on database level.

Does Deactivate/Reactivate of a SharePoint Feature Increment the Version?

We have a complex scenario which requires a timer job to run after content deployment to a SP 2010 site collection. The timer job automatically deactivates/reactivates a branding feature which is responsible for setting the master page for the site collection, among other things.
We have had several feature upgrades along the way, and neglected to call .Update() on the feature in that specific site collection. So all of the updated CSS, master page, page layouts etc. are out of date on that SC.
The strange part is that when I checked the version number of that feature in this SC, it shows as the latest version. The custom upgrade action clearly didn't run and update the files, because nobody called .Upgrade().
One of my colleagues suggested that the deactivate/reactivate process done by the timer job would update the version number, meaning that I can no longer call Upgrade()!
Is that true? Does a deactivate/reactivate cycle for a feature automatically update the feature version number?
Is there an easy way to fix this mess? Some way to decrement the version number programmatically, then call Upgrade()??
On 1: No. Feature deactivating / activating does not trigger an update. See this article by Chris O' Brian: http://www.sharepointnutsandbolts.com/2010/06/feature-upgrade-part-1-fundamentals.html
Feature upgrade does NOT happen automatically (including when the
Feature is deactivated/reactivated)! The only way to upgrade a Feature
is to call SPFeature.Upgrade(), typically in conjunction with one of
the QueryFeatures() methods. My tool which I’ll go on to talk about is
a custom application page which helps you with this part – note there
is no STSADM command, PowerShell cmdlet or user interface to do this
out-of-the-box.
Is your timer job cycling the feature activation with Force? Then, yes, it is triggering the feature upgrade/feature update see the following screenshot from SPFeature.Activate (see my yellow marking):
Why the feature version is incremented, I'm not sure. When you have a feature, install a new feature version and activate / deactivate, the feature version stays the same unless you run an Upgrade, see also this related question stating the same: https://sharepoint.stackexchange.com/questions/41476/feature-upgrading-question
I'm guessing your timer job is using force? Otherwise I'm not quite sure what is happening.
On 2: Don't know if it is possible to decrease the version number, but the safest way would be to just create a new version including a grand "clean up" feature receiver which sets everything correct, i.e. checks which steps of the feature upgrade have happened already (e.g. new list created, new content type added) and which haven't. Depending on that just execute the same steps again which have not executed yet. For the latter part you can fortunately use the existing code, so you would only need the "clean up" or checking code.
After some testing I found that simply deactivating and reactivating the feature will increment the version number and completely screw up your upgrade! I even watched the update come through in the content database. As soon as you deactivate/reactivate the updated feature, the new version number pops into the content DB. Of course the upgrade doesn't actually run, it just increments the version number.
This means that if you then call .Upgrade() it won't work because SharePoint thinks it's already been upgraded!!
To fix this I updated the row in the content database to set the feature version back to 0.0.0.0 for that particular web and then I could run .Upgrade() just fine....but that's not exactly a supported solution. If anyone else has a better idea drop a reply.

How to update a field in a post-op plugin?

I have a reason to prefer my plugin to be registered on post-op but I'd need to put something in it (change a field to another value). Do I really have to register it on pre-op or can I shove my update into it despite that the operation has been carried out already?
I'd prefer to avoid firing up an update. The code logic might get a bit crowdy and confusing by that, since there'll be a lot of stuff to do upon a "real" update.
Changes made to the target entity in post-op will not end up in the database unless you run an update manually.
You could consider breaking up your plugin into two. One to change the field in pre-op and one to do whatever it is you're doing in post-op.
Plugins can share data: http://msdn.microsoft.com/en-us/library/gg328579.aspx

Best Practices for Content Types in SharePoint

Recently, we came across a severe problem in production farm with the Content Types. I would like to explain the background of this problem first.
We have nice working feature for Content Types installation in production and test farms. We developed and deployed (using wsps) this SharePoint feature in Visual studio. We are using the publishing pages using page layouts and Content Types to help content editors to quickly publish the web pages. Unfortunately, some Content Types and site columns have been manually updated/added by some people in the production, so whenever I (developer) make some changes to the existing Content Types (using Visual Studio and feature activation/deactivation) , SharePoint removes one or two columns (during feature activation/deactivation) from Content Types; or the columns which have not been added in a best practice way. I think the best practice is to update Content Types using Visual Studio.
Now, I wish to ensure that site columns shouldn't get removed from Content Types upon feature activation/deactivation.
Note: Our feature for Content Type activation/deactivation doesn't hold any activation dependencies in the feature.xml
Recommended Approach
Based on all these factors, my suggestion would be to:
• Create two Features: one for the original markup and one for making changes. (Or you can put them in the same Feature; I just want to differentiate between where you do what.)
• The original Feature should contain the CAML for Site Columns and Content Types. This ensures the IDs have been assigned ahead of type and remain constant.
• If you want to update a Site Column by changing nearly anything about it except its Field type, do it using a Feature Receiver. By doing this, you can call the Update method and pass in a boolean indicating if you want all the existing assets in the site that inherit from this to update to, (something you couldn't do via the CAML.)
• You can also add an existing Site Column (that you provisioned via the CAML feature) to an existing Content Type (that was provisioned via the CAML feature). This is helpful if the Column was not part of that Content Type before, etc.
• In a scenario like the one I just mentioned in the last bullet point, it's necessary to deactivate and reactive the CAML feature (to provision the new assets) before calling your Feature Receiver. What will this mean for the site? Since all the Site Columns and Content Types in the lists in the site are using the same ID's as the ones provisioned in the Site Collection root, removing its parent from the Site Collection won't change that. It might leave it orphaned temporarily, (i.e. there will be no relationship between that item and an item in the Site Collection root, but it will function the same way it always has, since it's really a fully-functioning copy of the original item) until you reactivate the Feature that puts the item back in the Site Collection. It's like the parents are going on vacation when you deactivate the Feature, and are coming back home when you activate the Feature again.
You have a choice when it comes to how you maintain the CAML and the Feature Receiver, since you have two scenarios: existing Site Collections and new ones.
• You could make a policy that every time you write code in your Feature Receiver to update a Site Column or Content Type, you have to make the change in your CAML as well. That would mean that every time you activated the CAML Feature in a "fresh" Site Collection, the CAML would be up-to-date and accurate; there would be no need to run the "updater" feature. (In your Feature Receiver, you should make sure you do some extra checking to make sure a Site Column doesn't already belong to a Content Type before adding it, etc. in case that change is already in place before the code executes.) This approach means you only have to execute one Feature when creating a new Site Collection, but it also means you're maintaining changes in two places: in your Feature Receiver for making changes to existing sites, and in your CAML for new sites. It's a cleaner approach, but also contains an element of redundancy, which always leaves room for human error.
• The other approach is to simply assume that every time the base CAML feature is activated, you're always going to execute the Feature Receiver. This approach says the only time you'd change the CAML is to add a new Site Column or new Content Type; otherwise, all the changes happen in the Feature Receiver. This approach reduces redundancy, but also means your Feature Receiver code could get quite large with all your changes over time, and it could leave your CAML as very much "legacy" over time.
Src: http://blog.beckybertram.com/Lists/Posts/Post.aspx?List=eb3e1762%2Dbab0%2D4e96%2D8bc5%2Dd67d6e6bfd44&ID=18
Updating Content Types is still one of the underdeveloped portions of Sharepoint which sometimes causes trouble, especially in Content Deployment scenarios.
The best thing in your case would be to always avoid making any changes to content types by hand (using UI)
Whenever you are installing the content type, make sure that you remove the previous one and then install the new one. (Sometimes its not possible due to pages being already created out of it).
My current approach to deploying content types is to do as much as possible using code rather than CAML. That way it is easy to fully control the logic of updates, including ensuring that changes made manually don't cause conflicts. I have the structure defined as attributes on an interface I also use for strongly typed list access, but there are several other ways you could do it.
The only piece that isn't available in the API is setting a specific content type ID, so you need to have a caml file for that, but it's a small/simple file, doesn't try to make updates and is only referenced from a feature that will also run the update code.

Resources