Using JDBC you can call SQL procedures, which are Caché methods.
Additionally, you can access Caché objects and call methods via Caché Java binding.
- Log in to post comments
Using JDBC you can call SQL procedures, which are Caché methods.
Additionally, you can access Caché objects and call methods via Caché Java binding.
Thank you! Fixed the link.
Can you clarify your post with the code that causes error?
jQuery is a library - a big collection of "classes" and methods you can use anywhere. It makes no assumptions about how your application is built, has no internal DOM tree representation, etc.
Angular JS is an MVC framework - it forces your application to be structured in a very specific way, it manipulates DOM tree of the page according to specified rules. And well, it also provides a big collection of "classes" and methods you can use in your the code, but only the in parts you wrote in compliance with Angular architecture (scopes/controllers/services).
Please consider removing or at the very least modifying the description of:
intersystems-ru~REST 0.8.0-a Basic classes for REST web API on InterSystems Cache
It was only relevant with 2014-2015 REST and does not represent best practices for REST APIs in 2016.1+.
There are some problems with many namespace. I found that after I hit about a hundred namespaces on an instance it's time to purge. 50 seems to be the upper limit of easily manageable for me tbh. More, and scrolling in Studio/SMP takes too much time.
Do you have a call to CreateBusinessService somewhere in your code? It allows doing business service calls from non-Ensebble context (by well making current job Ensemble job). It's called like this (from Demo.ZenService.Zen.WeatherReportForm):
Set tSC=##class(Ens.Director).CreateBusinessService("Zen Service",.tService)Where first arguments is a host name of a business service. In your case the error appeared because the first argument is equal to EnsLib.SOAP.GenericService which is not present in currently running Ensemble production. You need to do one of the:
I'd like to add some commentary to Angular 1/2 comparison.
Angular 1:
- easier to hook to cache (can be used by calling the library from a csp and calling services cache rest)
That's same as with Angular 2.
- flatter learning curve if jquery is already known
- being so similar to jquery
jQuery has little in common with Angular. Angular (1 or 2) is an MVC framework and jQuery is the utilities library.
- not needed for really small projects
Yes, for both Angular 1 and 2.
- easier to maintain, perhaps, for someone who knows web, html and jquery
Highly debatable. Learning curve for Angular 1 is fairly steep.
Angular 2.
- does not work in browsers older than IE9
Angular 1 also does not work in browsers older than IE9
- keeps changing, it is not completely stable yet?
It has a stable version for a few months already.
Now, with that said, I'd like to recommend Angular 2. The main advantage in my opinion is that many fundamental problems present in Angular 1 were solved in Angular 2. Here's some links elaborating on differences between Angular 1 and 2:
That is almost what I started this topic with. I get a compilation error with this code. And fields data_Year and data_Month are not getting created it seems.
Thank you!
I copied your example, but SQL returns results saved on disk, which is expected as the data property is triggered computed
Class CS.Persistent Extends %Persistent
{
Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed ];
/// data getter method in SQL context
ClassMethod dataGetStatic() As %List
{
quit $lb(2017,1)
}
/// do ##class(CS.Persistent).test()
ClassMethod test()
{
do ..%KillExtent()
do $system.SQL.PurgeForTable($classname())
set obj = ##class(CS.Persistent).%New()
set obj.data.Month=-1
set obj.data.Year=0
set sc = obj.%Save()
write !,"Save: ",$s($$$ISOK(sc):"OK", 1:$System.Status.GetErrorText(sc)),!
zw ^CS.PersistentD
do ##class(%SQL.Statement).%ExecDirect(,"select * from "_$classname()).%Display()
}
}I execute in a terminal:
do ##class(CS.Persistent).test()
And I receive the following output:
Save: OK
^CS.PersistentD=1
^CS.PersistentD(1)=$lb("",$lb(0,-1))
ID data_Month data_Year
1 -1 0Can I make a serial class always computed?
I want to receive the following output:
Save: OK
^CS.PersistentD=1
^CS.PersistentD(1)=$lb("",$lb(0,-1))
ID data_Month data_Year
1 1 2017Thank you.
How can I make it work from SQL context too?
Can you post request code?
There should not be a problem with underscores:
set obj = ##class(%DynamicObject).%FromJSON("{""a_b"":1}")
w obj."a_b"
>1Macros can eliminate using $method/dynamic dispatch here altogether.
Macros for method names which compile into AmethodName or methodName depending on global var set for compilation then.
Dynamic dispatch is a hit on speed anyway.
Always call
do a.AmethodName()
And inside dynamic dispatch check global variable %debug (or global, or some IsDebug method etc.). If it exists call both annotation methods and target method, If it does not exist only call target method.
Another approach would be using dynamic dispatch:
Let's say you have this method:
/// @NiceTest1
ClassMethod Test()
{
Write 1
}Using Class Generators you generate 2 additional methods:
/// @NiceTest1
ClassMethod OnBeforeTest()
{
Write "Before NiceTest1"
}
/// @NiceTest1
ClassMethod OnAfterTest()
{
Write "After NiceTest1"
}and you add dynamic dispatch method (and dynamic dispatch classmethod) to the class:
/// Is used to implement an unknown method call. It is also used
/// to resolve an unknown multidimensional property reference (to get the value
/// of a property) because that syntax is identical to a method call.
Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ]
{
// Amethod -> method
set Method = $e(Method, 2, *)
do $method(, "OnBefore" _ Method, Args...)
do $method(, Method, Args...)
do $method(,"OnAfter" _ Method,Args...)
}So, as a whole it can look like this:
Class Utils.Annotations1 Extends %RegisteredObject
{
Method OnBeforeTest()
{
Write "Init NiceTest1",!
}
/// @NiceTest1
Method Test()
{
Write 1,!
}
Method OnAfterTest()
{
Write "End NiceTest1",!
}
/// Is used to implement an unknown method call.
Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ]
{
set Method = ..getMethodName(Method)
do $method(, "OnBefore" _ Method, Args...)
do $method(, Method, Args...)
do $method(,"OnAfter" _ Method,Args...)
}
/// Is used to implement an unknown class method call
ClassMethod %DispatchClassMethod(Class As %String, Method As %String, Args...) [ ServerOnly = 1 ]
{
set Method = ..getMethodName(Method)
do $classmethod(, "OnBefore" _ Method, Args...)
do $classmethod(, Method, Args...)
do $classmethod(,"OnAfter" _ Method,Args...)
}
ClassMethod getMethodName(method As %String) As %String
{
// Amethod -> method
set method = $e(method, 2, *)
return method
}
}Works like this:
USER>do a.ATest() Init NiceTest1 1 End NiceTest1 USER>do a.Test() 1
You can modify method code during compilation (obviously dangerous) using generators. Here's the sample that annotates all methods, containing @ in description:
Class Utils.Annotations
{
/// @NiceTest1
ClassMethod Test()
{
Write 1
}
ClassMethod OnCompile() As %Status [ CodeMode = objectgenerator ]
{
#dim sc As %Status = $$$OK
for i=1:1:%class.Methods.Count() {
#dim method As %Dictionary.MethodDefinition = %class.Methods.GetAt(i)
if method.Description [ "@" {
set sc = ..annotate(method)
quit:$$$ISERR(sc)
}
}
quit:$$$ISERR(sc) sc
set sc = %class.%Save()
quit sc
}
ClassMethod annotate(method As %Dictionary.MethodDefinition) As %Status
{
#dim sc As %Status = $$$OK
set code = method.Implementation.Read($$$MaxCacheInt)
set code = ..cleadOldAnnotation(code)
set code = ..addNewAnnotation(code, $e(method.Description, 2,*))
do method.Implementation.Clear()
do method.Implementation.Write(code)
quit sc
}
ClassMethod cleadOldAnnotation(code As %String) As %String
{
if $find(code, "//init annotation end") {
set code = $e(code, $find(code, "//init annotation end") + 2, $find(code, "//complete annotation start") - $l("//complete annotation start") - 2)
}
return code
}
ClassMethod addNewAnnotation(code As %String, annotation As %String) As %String
{
#define Tab $c(9)
set code = $$$Tab _ "Write ""Init " _ annotation _ """" _ $$$NL _
$$$Tab _ "//init annotation end" _ $$$NL _
code _
$$$Tab _ "//complete annotation start"_ $$$NL _
$$$Tab _ "Write ""End " _ annotation _ """"
return code
}
}Compiles into:
/// @NiceTest1
ClassMethod Test()
{
Write "Init NiceTest1"
//init annotation end
Write 1
//complete annotation start
Write "End NiceTest1"
}
Yes, you can query everything you see in Message Viewer and Event Viewer. Their code is defined in EnsPortal.MessageViewer.zen and EnsPortal.EventLog.zen respectively. You can see the queries these pages use and adapt them, or inherit from them and publish it as another separate web application.
Also, here's modification example - Ensemble Log Viewer with namespace support.
You need:
You can specify Logfile setting for logging and these settings for debug:
%DB_CACHESYS may also be required, because data for this table is stored in CACHESYS database.
Atelier accesses web port, which can be open.
Thank you!
Do you import code from GitHub repository into Ensemble instance automatically?
you are entirely correct.
Good to hear.
$$$SIMSRCDOMENT
If I change algorithm to $$$SIMSRCDOMENT I don't receive any results (Results local is undefined).
If I choose $$$SIMSRCEQUIVS or $$$SIMSRCSIMPLE I get Results local as expected.
What may be the reason? I didn't modify the domain between runs.
Method returns $$$OK and %objlasterror is empty using any algorithm.
You can ran them from a terminal.
Yes, same as with studio, Caché supports Unit Tests. Documentation.
write ##class(Config.CPF).Activate()
Would read and activate current configuration file without system restart.