Is Infolog an alias to the class Info in Dynamics AX? - axapta

I am trying to understand how Infolog works within Dynamics AX. I understand that the following code will display the text in the infolog window.
info("Hello World!");
I am aware that info is a static method on the Global class and therefore the method can be called by simply calling the name without actually specifying Global::
While looking into the method info in class Global, I noticed that it invokes infolog.add. Right-clicking on add and selecting the option Lookup Definition takes me to the method add in the class Info.
If the class in which the method add exists is named as Info, how is it being called from within Global::info() with the name Infolog?
The only logical conclusion that I can arrive at is that Infolog is an alias for the class Info. If that is correct, where is this alias defined in the AOT (Application Object Tree)?
I searched the AOT but found multiple references to the term Infolog but I couldn't find anything that would directly relate to an Application or System class.

The response to the same question I posted on Microsoft Dynamics communities forum helped me to understand the code better.
Is Infolog an alias to the class Info? - Response on Microsoft Dynamics Community forum
Below shown code is from the static method Global::info(). I failed to notice that call to method add using the object infolog is actually an instance method and not static.
client server static Exception info(
SysInfoLogStr txt,
URL helpUrl = '',
SysInfoAction _sysInfoAction = null)
{
return infolog.add(Exception::Info,
getPrefix()+txt,
helpUrl,
_sysInfoAction, false);
}
In other words, infolog is an instance of class Info. After looking into the class Info, I found the startup method. I kept a breakpoint to debug the code and found that this method is called whenever the AX client is opened. This method in turn calls another method named initBrowser. Within the initBrowser, the following code seems to initialize the global instance of Infolog using a windows handle.
this.initializeInfolog(this.browser().hWnd());
The above menthod initializeInfolog exists in the System class xInfo, which is the parent class of Info. Since I cannot look into the class xInfo, I assume that this is where the instance of class Info with the name infolog is being created.

I don't think it's an alias. I think it's a global variable defined in the kernel level.
Edit: You answered your question while I was answer it...

Related

NullPtr exception while getting country names and country codes in backoffice

After upgrading to Intershop CM 7.10.18.1, we are getting NullPtr exceptions while opening store detail page in backoffice.
ISML template for store details is EditStore_52.isml, which includes ISCountrySelectBox module, which futhermore calls getCountryNamesAndCodes() method.
That method fails with NullPtr exception because of underlined call which returns null.
We are wondering whether this is a bug and whether the intended code was supposed to be:
countriesMap.put(country.getId(), country.getDisplayName(currentLocale));
Please advise on workaround for this situation.
The following is a stack trace for exception.
Intershop delivers address data which can be imported/export through Operations backoffice (e.g. Login at https://localhost:8443/INTERSHOP/web/WFS/SLDSystem using Organization Operations). Out of the box such address data looks like this:
<country>
<id>DE</id>
<custom-attributes>
<custom-attribute dt:dt="string" name="displayName" xml:lang="de-DE">Deutschland</custom-attribute>
<custom-attribute dt:dt="string" name="displayName" xml:lang="fr-FR">Allemagne</custom-attribute>
<custom-attribute dt:dt="string" name="displayName" xml:lang="en-US">Germany</custom-attribute>
</custom-attributes>
</country>
As you can see, it only contains displayName attribute values for de-DE, fr-FR and en-US. A possible workaround in your case would be to export data, include missing attribute values and import it again.
Please note: The work to deliver a fix for this is already in progress. I'm sorry for the inconvenience.
The more convenient way (because editing xml import files is tedious) would be to replace the erroneous implementation using guice module override. In a nutshell:
Copy paste the original implementation of class com.intershop.component.region.internal.geoobject.LocalizedCountryNamesProviderImpl into a class of your own in your custom cartridge. For example: I just created a class AppSFLocalizedCountryNamesProviderImpl in cartridge app_sf_responsive to test this.
Adapt above method according to your needs
Create an override module (See Cookbook - Dependency Injection and ObjectGraphs). Following my example the modules configure operation should look like this:
#Override
protected void configure()
{
bind(LocalizedCountryNamesProvider.class).to(AppSFLocalizedCountryNamesProviderImpl.class);
bindProvider(com.intershop.component.foundation.capi.localization.LocalizedCountryNamesProvider.class)
.to(AppSFLocalizedCountryNamesProviderImpl.class);
}
Publish your cartridge, Restart your server

How to create Context object, which is required in calling SQLiteOpenHelper constructor

I am creating some hack kind of thing in existing android code to verify database creation and its accessibility across layers in application.
For this I have modified an existing function of .java file but I am facing an issue while calling constructor of SQLiteOpenHelper.
The signature is SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
And I don't know how to create this Context instance. From googling I am seeing it is being some kind of activity class instance.
What ways are there to create this Context instance? Do we have to have activity class implemented?
Have a look at this question. It shows how to obtain a reference to the current Context object statically.
The gist of it is that you have to store a reference to the context that can be accessed statically from other sections of code.
P.S. You can't really "create" a context. That is something that is provided to you by the Android platform.
Just call:
this.getApplicationContext()
from wherever you are trying to create the instance of SQLiteOpenHelper.

How do I call a method from a Domain Service class

Once again I am in need of some assistance with regard to calling a Domain Service class method from silverlight.
This ties in somewhat to my question of yesterday which was solved. Thanks again!
For those who are interested, my question of yesterday can be found here:
Using ASP.net membership to get aspnet_Users in silverlight
Now onto my current question.
I have the following method in Domain Service Class called MembershipData
[RequiresRole("Managers")]
public void DeleteUser(MembershipServiceUser user)
{
Membership.DeleteUser(user.UserName);
}
This code is from kylemc's tutorial
Now how do I call this method from within Silverlight?
I understand from yesterday's question that
public IEnumerable<MembershipServiceUser> GetAllUsers()
needs to be called by defining the query, then running the query and then calling OnGetAllUsersLoaded when the the results return.
What I am unsure of is, Do you need to call the method in this way because of its return type?
Obviously public void DeleteUser(MembershipServiceUser user) has no return type so cannot be called in this way.
It does not seem to be possible to do:
MembershipDataContext context = new MembershipDataContext();
MembershipServiceUser user = new MembershipServiceUser();
user.UserName = "bob";
context.DeleteUser(user);
But then how do I use the DeleteUser method?
Any assistance is greatly appreciated.
Kind regards,
Neill
Update
Thanks for the info HiTech. I still have one issue I need to solve. Perhaps I am still not doing something correctly.
I am now creating a new instance of MembershipServiceUser, lets call it msu.
Then assigning msu.UserName and msu.Email the user details, and after that calling
context.MembershipServiceUsers.Remove(msu)
where context is my MembershipData domain service context, and I have checked that
context MembershipServiceUsers results
does have my user info. I then however get the following error
"The specified entity is not contained in this EntitySet."
I am positive the data in msu is correct, so any ideas as to why I am getting this error?
Many thanks
Update 2
Am I on the right track with something like the following...
MembershipServiceUser usr = (from a in context.MembershipServiceUsers
where a.UserName == "bob"
select a).First();
context.MembershipServiceUsers.Remove(usr);
context.SubmitChanges(DeleteUser_completed, null);
Or is this way off? because in my callback DeleteUser_completed(SubmitOperation so)
so.HasError = true
while so's ChangeSet -> RemovedEntities = 1, but so's EntitiesInError's result is "enumeration yielded no results"
Once again thanks for helping steer me in the right direction.
RIA services works by creating a change set (literally a set of changes) and sending just those changes to the server. The methods to do CRUD are more like Entity Framework, not direct method calls.
On the client side you will call the Remove method on the domain context's User collection.
On the receiving side it goes through all the changes and says:
Q. "Is this an object deletion?"
A. Yes...
Q. "What object type is it?"
A. MembershipServiceUser
Q. "Do we have a method called Delete that takes a MembershipServiceUser parameter?"
A. Yes...
It then calls that method with the object from the changeset...

ASP.Net SqlWebEventProvider - Raising custom event - Cannot access WebErrorEvent due its protection level

I use SqlWebEventProvider to log the exceptions to sql server, and it works fine.
I also want to log custom exceptions to aspnet_WebEvent_Events table programmatically. Similar to - http://fredrik.nsquared2.com/viewpost.aspx?PostID=107&showfeedback=true
WebBaseEvent.Raise(new WebErrorEvent("My Error message", null, 5000, e));
I get an error saying "Cannot access constructor 'WebErrorEvent' here due its protection level.
Appreciate your comments...
If you wish to log custom events, you may consider creating your own event by inheriting from one of the predefined event classes found in System.Web.Management.
Here is a good reference written by Scott Mitchell. It is pretty easy to follow
https://web.archive.org/web/20211020121454/https://www.4guysfromrolla.com/articles/062707-1.aspx
The constructor for class WebErrorEvent is private. You can't instantiate an object of this class.
Take a look at Using Access Modifier private with Constructor in the article titled What are constructors in CSharp - A Step Ahead Series?.

How to implement callbacks in Java

I have a class called CommunicationManager which is responsible for communication with server.
It includes methods login() and onLoginResponse(). In case of user login the method login() has to be called and when the server responds the method onLoginResponse() is executed.
What I want to do is to bind actions with user interface. In the GUI class I created an instance of CommunicationManager called mCommunicationManager. From GUI class the login() method is simply called by the line
mCommunicationManager.login();
What I don't know how to do is binding the method from GUI class to onLoginResponse(). For example if the GUI class includes the method notifyUser() which displays the message received from theserver.
I would really appreciate if anyone could show how to bind methods in order to execute the method from GUI class (ex. GUI.notifyUser()) when the instance of the class mCommunicationManager receives the message from the server and the method CommunicationManager.onLoginResponse() is executed.
Thanks!
There's two patterns here I can see you using. One is the publish/subscribe or observer pattern mentioned by Pete. I think this is probably what you want, but seeing as the question mentions binding a method for later execution, I thought I should mention the Command pattern.
The Command pattern is basically a work-around for the fact that java does not treat methods (functions) as first class objects and it's thus impossible to pass them around. Instead, you create an interface that can be passed around and that encapsulates the necessary information about how to call the original method.
So for your example:
interface Command {
public void execute();
}
and you then pass in an instance of this command when you execute the login() function (untested, I always forget how to get anonymous classes right):
final GUI target = this;
command = new Command() {
#Override
public void execute() {
target.notifyUser();
}
};
mCommunicationManager.login(command);
And in the login() function (manager saves reference to command):
public void login() {
command.execute();
}
edit:
I should probably mention that, while this is the general explanation of how it works, in Java there is already some plumbing for this purpose, namely the ActionListener and related classes (actionPerformed() is basically the execute() in Command). These are mostly intended to be used with the AWT and/or Swing classes though, and thus have features specific to that use case.
The idiom used in Java to achieve callback behaviour is Listeners. Construct an interface with methods for the events you want, have a mechanism for registering listener object with the source of the events. When an event occurs, call the corresponding method on each registered listener. This is a common pattern for AWT and Swing events; for a randomly chosen example see FocusListener and the corresponding FocusEvent object.
Note that all the events in Java AWT and Swing inherit ultimately from EventObject, and the convention is to call the listener SomethingListener and the event SomethingEvent. Although you can get away with naming your code whatever you like, it's easier to maintain code which sticks with the conventions of the platform.
As far as I know Java does not support method binding or delegates like C# does.
You may have to implement this via Interfaces (e.g. like Command listener.).
Maybe this website will be helpful:
http://www.javaworld.com/javaworld/javatips/jw-javatip10.html
You can look at the swt-snippets (look at the listeners)
http://www.eclipse.org/swt/snippets/
or you use the runnable class , by overwritting the run method with your 'callback'-code when you create an instance

Resources