How to differentiate if a TBO is called when importing new Document vs for any other operations - documentum

We are trying to add one additional feature to our method for TBO. The feature needs to be executed only when a new document for that object type is imported and should not be executed in any other case like checkin checkout or any changes in attributes.
However the new code is getting called everytime we make any changes to attribute to that document.
We have put that code in doSave() method.
I tried isNew method for distinguish between newly imported Document and other scenarios, however could not get success, may be missing the usage details of the method.
Can anyone suggest anything?
We are on Documentum version 7.2.

I always use isNew() method to check is object new or versioned, I don't remember having problems with it at any DFC version.
Only one thing that comes in mind is to make sure you don't use super.doSave() while inside the code since right after it method will return false.
But this is expected behaviour.
If you really need to do this - some calulations based on programatically preset data - make sure you use value saved within local variable throughout your code.
If you think you are experiencing bug with the method try with another DFC version or report a bug to the Support.

Related

Is it a good practice the attach an event related parameter to an object's model as a variable?

This is about an API handling the validation during saving an object. Which means that the front-end client sends a request to the API to a specific end point, then on the back-end the API creates a new object if the right conditions are meet.
Right now the regular method that we use is that the models has a ruleset for each fields and then the validation is invoked when the save function is invoked, but technically the validation is done right before the object is saved into the database.
Then during today's code review I came across a solution which I wasn't sure if it's a good practice or not. And it was about that the front-end must send a specific parameter to the API every time. This is because other APIs are using our API as well, and we needed to know if the request was sent as and API request or a browser request. If this parameter is present then we want to execute an extra validation function on a specific field.
(1)If I would have to implement it, then I would check the incoming parameter in the service handler or in the controller level, and if I got one, I would invoke the validation right away, and if it fails I would throw an error.
(2)The implementation I saw however adds an extra variable to the model, and sets the model variable when there is an incoming parameter, then validates only when the save function is invoked on the object(which first validates the ruleset defined on the object fields, then saves the object into the database)
So my problem with (2) is that the object now grown bigger with an extra variable that is only related to a specific event. So I would say it's better to implement (1). But (2) also has an advantage, and that is when you create the object on different end point by parsing the parameters, then the validation will work there as well, even if the developer forget to update the code there.
Now this may seems like a silly question because, why would I care about just 1 extra variable, but this is like a bedrock of something good or bad. So if I say this is ok, then from now on the models will start growing with extra variables that are only related to specific events, which I think should be handled on the controller/service handler level. On the other hand the code would be more reliable if it's not the developer who should remember all the 6712537 functionalities and keep them in mind when makes some changes somewhere. Let's say all the devs will get heart attack tomorrow from the excitement of an amazing discovery, and a new developer has to work on the project while he doesn't know about these small details, and then he has to change something on the code that is related to this functionality - so that new feature should be supported by this old one as well.
So my question is if is there any good practice on this, and what do you think what would be the best approach?
So I spent some time on thinking on the solution, and I think the best is to have an array of acceptable trigger variables in the model class. Then when the parameters are passed to the model on the controller level, then the loader function can be modified that it takes the trigger variables from the parameters and save it in the model's associative array variable that stores the trigger variables.
By default this array is empty, and it doesn't matter how much new variables are needed to be created, it will only contain the necessary ones when those are used.
Then of course the loader function needs to be modified in a way that it can filter out the non trigger variables as well as it is done for the regular fields, and there can be even a rule set of validation on the trigger variables if necessary.
So this solves the problem with overgrowing the object with unnecessary variables and the centralized validation part, because now the validation can be always done in the model instead of the controller.
And since the loader function is modified to store the trigger variables in the model's trigger variables array variable, the developer never has to remember that this functionality was created. Which is good, because in the future when he creates a new related function or end point that should handle object creation, he will not miss it to validate it against the old functionality, because the the loader function that he modified in the past like this will handle it for him.
It needs to be noted tho, that since the loader function doesn't differentiate between the parameters, and where to load them other then checking the names of the parameters with the filter functions, these parameter names should be identical from each other, otherwise a buggy functionality can be created accidentally. Like if you forget that a model attribute with the same name was used, then you can accidentally trigger an event that was programmed to be triggered if the trigger variable with the same name is present. However this can be solved by prefixing the trigger variables for example.

ActorSystem.Create() ignores config

I am trying to instantiate an actor system with non-default behaviour (e.g. clustering or remoting) but no matter what I do the ActorSystem always ends up with default configuration. The config object and settings object appear correct (e.g. actor.provider == cluster) but the actual run-time object always has defaults.
I've tried constructing the config many different ways. With App.config cdata and by manually parsing a config file with ConfigurationFactory and passing it in to Create. I had the problem with 1.4.3 and with 1.3.17.
I downloaded the Akka source code and debugged it. Stepping through the Create method I found that the root HoconObject's items dictionary contains 2 entries with the key "akka". One entry is mine, the other looks like a fallback. The getter method resolves the fallback.
I guess there is some weird string formatting happening...
[Update] There seems to be confusion about what is actually happening. Here is a screen-shot of what HoconObject looks like when it works:
In the screen-shot you can clearly see a single entry in the Items dictionary for "akka" that is set to "provider=cluster", which isn't the default and is coming from the config file. The previous screen-shot shows 2 entries, one of which is "provider=cluster" and the other is clearly the default that Akka injects. Both key = "akka". The bug causes Akka to select the default rather than the override.
I understand that Hocon allows overrides from defaults but that isn't what's happening. Again, if you look at the source code for HoconObject you'll see the screen-shot is of a plain .Net dictionary called 'Items' and the TryGetValue is the .Net implementation... not a Hocon implementation.
This is obviously a parsing bug that cases Akka to behave incorrectly and throw no exceptions.
I don't have enough reputation to post my question as a comment.
Do you have a code I can use to replicate the problem? A code snippet of how you build your config would be fine.
I downloaded the Akka source code and debugged it. Stepping through the Create method I found that the root HoconObject's items dictionary contains 2 entries with the key "akka". One entry is mine, the other looks like a fallback. The getter method resolves the fallback.
Yes, this is the actual behavior of a HoconValue. a HoconValue is a list of value fragments that will be converted into a proper data type when you call the appropriate getter function. For example, the HoconValue instance that you see in your debug session is actually 2 HoconObject fragments, and the proper merged object can be retrieved by calling the GetObject() function of that HoconValue instance.

Check original language of repository objects at creation?

In our company, repository objects must be created with original language EN.
Is there a way to check the logon language in case of creating a new object in the ABAP repository?
Desired behaviour:
SE80 - Create program/class/data element/table/....
==> user exit/badi checks the logon language. When it is not 'EN', the creation will be refused.
regards,
Umar Abdullah
I know there is a exit for this but I haven't remember exact name. You can use general purpose for finding exit. Go to SE24 and open CL_EXITHANDLER class, find GET_INSTANCE method and add break point. Then start creating item, it will pause on debugger multiple times, try to find suitable one.
As #mkysoft suggested, you may implement a check in the BAdI CTS_REQUEST_CHECK, method CHECK_BEFORE_ADD_OBJECTS, which is invoked when the object is about to be attached to a transport request. Raise the exception CANCEL to make the attachment fail (and so the object is not created too).
EDIT: sorry, ignore my answer, "this method is NOT released for Customer usage" as said in note 2150125 - Method CHECK_BEFORE_ADD_OBJECTS not triggered
DISCLAIMER: THE METHOD DESCRIBED HERE IS ABSOLUTELY NOT RECOMMENDED.
As correctly pointed out by the other members there is no standard and customer-exposed method to achieve your requirement, but if you absolutely must enable this check during creation you can use the below method. As well as the previously offered to you, it also involves modification of SAP standard.
There is a system BAdi CTS_TADIR_SUBSCREEN that is located inside enhancement point CTS_ES_TADIR_POPUP. They are SAP internal and not released for customer usage, so do this at your own risk.
Implementation procedure:
Step 0. First thing you need to change is a SAP internal usage flag, for which you need Object Access key which can be obtained from SAP or from SAP partner that made the implementation in your org. In virgin state this BAdi throws the error if you try to implement it
So hereinafter we assume that you already ticked off this checkbox in BAdi settings
Step 1.
In order to implement the BAdi one need to implement enhancement spot prior to that. This is the most complicated part, because despite we disabled internality flag the SAP-namespaced enhancements must be stored only in SAP-namespaced objects. By SAP namespace I mean non-Z, non-Y and non-T (Test). This means to implement this enhancement, besides modifying the enhancement definition, one need to create, for example, CTS_ES_TADIR named enh.impl., and save it to non-Z package, which you also need to create. Your enhancement implementations selector should look somehow like this
On the above screen only the second will work, all the rest Z will not.
Every non-Z object need Object Access Key, remember? Too bad. But just to show the proof-of-concept, I will proceed.
Step 2. After you created the enh. implementation in SAP-namespace it will propose you to create the BAdi implementation. The same principle applies here: only SAP-namespaced container for SAP-namespaced objects, hence CTS_TADIR_SUBSCREEN should have implementing class for example CL_TADIR_SUBSCREEN. During the creation of enhancement you will see many warnings
but finally you should have something like this, where all system-named objects are created and the enhancement/BAdi is activated.
Step 3. In order to get the BAdi working we need to enable this subscreen processing
during the playing with enhancement I found out that BAdi class is not being triggered standalone, without screen events not enhanced, so to make it work you need to touch a screen enhancement for screen 100
If you do not wanna modify screen elements logic, just put the dummy enhancement in SHOW_TADIR dialog module in the end of the include LSTRDO18
PROCESS BEFORE OUTPUT.
MODULE SHOW_TADIR. "<-- create the dummy enhancement here
CALL SUBSCREEN subs_info INCLUDING gv_badi_prog gv_badi_dynnr.
for example declaration statement like I did
Step 4. Activate your created BAdi class and put the necessary logic there. I wasn't able to trigger method GET_DATA_FROM_SCREEN, but PUT_DATA_TO_SCREEN worked fine
If we put this simple processing for your requirement
METHOD cts_if_tadir_subscreen~get_data_from_screen.
IF object_data-l_mstlang <> 'E'.
MESSAGE 'Objects in non-English languages are not allowed!' TYPE 'A'.
ENDIF.
ENDMETHOD.
it will not allow creating objects in languages other than English.
The check in method get_data_from_screen is being done before showing the screen so language is determined from system logon settings. If to play more with this BAdi, I suppose the method GET_DATA_FROM_SCREEN can also be enabled, which will make it possible to check user input, i.e. the case when the user gonna change the default language.

IBM Worklight - JSONStore logic to refresh data from the server and be able to work offline

currently the JSONStore API provides a load() method that says in the documentation:
This function always stores whatever it gets back from the adapter. If
the data exists, it is duplicated in the collection". This means that
if you want to avoid duplicates by calling load() on an already
populated collection, you need to empty or drop the collection before.
But if you want to be able to keep the elements you already have in
the collection in case there is no more connectivity and your
application goes for offline mode, you also need to keep track of
these existing elements.
Since the API doesn't provide a "overwrite" option that would replace the existing elements in case the call to the adapter succeeds, I'm wondering what kind of logic should be put in place in order to manage both offline availability of data and capability to refresh at any time? It is not that obvious to manage all the failure cases by nesting the JS code due to the promises...
Thanks for your advices!
One approach to achieve this:
Use enhance to create your own load method (i.e. loadAndOverwrite). You should have access to the all the variables kept inside an JSONStore instance (collection name, adapter name, adapter load procedure name, etc. -- you will probably use those variables in the invokeProcedure step below).
Call push to make sure there are no local changes.
Call invokeProcedure to get data, all the variables you need should be provided in the context of enhance.
Find if the document already exists and then remove it. Use {push: false} so JSONStore won't track that change.
Use add to add the new/updated document. Use {push: false} so JSONStore won't track that change.
Alternatively, if the document exists you can use replace to update it.
Alternatively, you can use removeCollection and call load again to refresh the data.
There's an example that shows how to use all those API calls here.
Regarding promises, read this from InfoCenter and this from HTML5Rocks. Google can provide more information.

Unloading a data reference in Entity Framework

Currently I am struggling with a Entity Framework issue. I have a wcf service that sits on top of the ef framework, and allows queries to the framework. At some point the user is able to request a file from the framework. The files are referenced by solution entries, so when you request a file from a solution, the reference is loaded to gain access to the file store.
That all works fine, but from that point onward, whenever you do another query that returns that solution entry, the whole file gets attached to the return result. I need some way of detaching or unloading the reference, such that the result entries will only contain an unloaded reference to the file store again.
I have tried to create a new context and query that context to retrieve information from, but when I do that, the entity in the original context is also changed.
I have tried to detach the entity from the original context and then query from the new context. That does not work either.
I have found one way of doing this. For all the non file-download queries, I detach the result entity, and send that over the wire. I am not sure if that is the best way to go about it though.
I hope someone might be able to provide some insight, thanks for the effort.
The issue you are experiencing is probably do to Change Tracking, which is on by default.
Possible Solution:
Disable Change Tracking with MergeOption.NoTracking
using (MyEntities _context = new MyEntities())
{
_context.Widgets.MergeOption = MergeOption.NoTracking;
return _context.Widgets.ToList();
}
This article may help to point you in the right direction on how to handle this issue if the solution above does not work.
I struggled with a similar issue recently. The problem was the result of the context maintaining a reference to the object I was using (obviously). Every time I made a change to an object of the same type, even when obtained with a new context (so I thought), the object was being changed.
With help from one of my peers, we determined the context was hanging around due to the way I was registering it with my IoC container (lifestyle per web request). When I changed the lifestyle to transient (which definitively provided a new instance) then changes to objects of the same type were unaffected.
Hope this helps.