Hola Hector, la verdad es que no entiendo bien que quieres hacer. Puedes darnos más detalles
- Inicie sesión para enviar comentarios
Hola Hector, la verdad es que no entiendo bien que quieres hacer. Puedes darnos más detalles
Hola,
Caché ya me suena antiguo pero en cualquier caso siempre lo puedes descargar desde http://wrc.intersystems.com si no tienes cuenta intenta desde http://download.intersystems.com
No me lo pierdo, ya es hora de practicar mi Mandarín!
Chicos y chicas aprovechad esta oportunidad para certificarse. Paso 1: REGISTRARSE en el VS2020
Hay tiempo de preparar el examen ya que se puede realizar online en cualquier momento hasta el 31 de Diciembre.
¿Qué os parece si hacemos una serie de webinars explicando los contenidos como preparación para el examen?
No se cómo ha quedado tu versión del código final ni cuándo se produce el error, ¿al compilar? ¿puedes pasar el código final?
Glup, eso no me lo esperaba!!... tendría que mirar desde cuándo está el JSON Adaptor
Pero para tu problema eso va a dar igual, me explico. El parámetro "jsonObject" es el que utiliza esa clase %JSON.Adaptor pero esa clase lo único que hace es ayudarte a manejar objetos JSON. Para resolver tu problema inicial en lugar de usar esa clase utiliza como tu dices un Stream. Por ejemplo el %Stream.GlobalCharacter.
Esta sentencia:
set tSC=..PostJSON(tURL,.tHttpResponse,pRequest.orden)
Lo que hace es pasar la URL, el objeto donde se va a colocar la respuesta a la vuelta (por referencia) y el contenido del mensaje pRequest. En este caso puedes inventarte un objeto tuyo que lleve un Stream con un JSON en texto plano para probar.
En este método:
Method PostJSON(pURL As %String, Output pHttpResponse As %Net.HttpResponse, pStream As %Stream.GlobalCharacter) As %Status
{
Return ..SendHTTP("POST",pURL,.pHttpResponse,pStream)
}
cambia la firma del método para usar el Stream. Y finalmente en este método envía el contenido como Body de la llamada HTTP.
Method SendHTTP(pHttpVerb As %String, pURL As %String, Output pHttpResponse As %Net.HttpResponse, pStream As %Stream.GlobalCharacter) As %Status
{
set httpRequest = ##class(%Net.HttpRequest).%New()
set httpRequest.ContentType = "application/json"
if $IsObject(jsonObject) {
set tSC=httpRequest.EntityBody.CopyFrom(pStream)
if $$$ISERR(tSC)
quit tSC
}
set tSC = ..Adapter.SendFormDataURL(pURL,.pHttpResponse,pHttpVerb,httpRequest)
quit tSC
}
No lo he probado. Creo que el uso del método CopyFrom es correcto pero si te falla es fácil copiar el contenido de un Stream a otro mediante Write y Read.
Espero que te sirva.
Para empezar veo que estás creando una clase Adaptador que hereda de Test.BO.Adapter.HTTPOutboundAdapter. Eso no es una Operación. Es un adaptador.
Y la verdad no veo dónde estás metiendo los datos del Body... quizá hay más código
Yo mejor haría una operación que herede de EnsLib.REST.Operation.
Ejemplo:
Class demo.bo.RESTOperation Extends EnsLib.REST.Operation
{
Parameter INVOCATION = "Queue";
Method SendHTTP(pHttpVerb As %String, pURL As %String, Output pHttpResponse As %Net.HttpResponse, jsonObject As %JSON.Adaptor) As %Status
{
set httpRequest = ##class(%Net.HttpRequest).%New()
set httpRequest.ContentType = "application/json"
if $IsObject(jsonObject) {
set tSC=jsonObject.%JSONExportToStream(httpRequest.EntityBody)
if $$$ISERR(tSC) quit tSC
}
set tSC = ..Adapter.SendFormDataURL(pURL,.pHttpResponse,pHttpVerb,httpRequest)
quit tSC
}
Method PostJSON(pURL As %String, Output pHttpResponse As %Net.HttpResponse, jsonObject As %JSON.Adaptor) As %Status
{
Return ..SendHTTP("POST",pURL,.pHttpResponse,jsonObject)
}
Method OnPostRequest(pRequest As demo.PostRequest, Output pResponse As demo.PostResponse) As %Status
{
set tURL=..Adapter.URL_"/demo"
set tSC=..PostJSON(tURL,.tHttpResponse,pRequest.orden)
if $$$ISERR(tSC)&&$IsObject(tHttpResponse)&&$IsObject(tHttpResponse.Data)&&tHttpResponse.Data.Size {
set tSC=$$$ERROR($$$EnsErrGeneral,$$$StatusDisplayString(tSC)_":"_tHttpResponse.Data.Read())
}
if $$$ISERR(tSC) quit tSC
// procesar respuesta
set pResponse = ##class(demo.msg.PostResponse).%New()
set pResponse.respuesta = ##class(demo.msg.Respuesta).%New()
if tHttpResponse.StatusCode=200 {
$$$TRACE(tHttpResponse.Data.Read())
set tSC = pResponse.respuesta.%JSONImport(tHttpResponse.Data)
} else {
set tSC=$$$ERROR($$$EnsErrGeneral,"HTTP Status:"_tHttpResponse.StatusCode)
}
quit tSC
}
XData MessageMap
{
<MapItems>
<MapItem MessageType="demo.PostRequest">
<Method>OnPostRequest</Method>
</MapItem>
</MapItems>
}
}Puede que me equivoque, pero estoy viendo un 500 Internal Server Error, eso es un error que te devuelve el servicio. Por lo tanto ni siquiera se producen los mensajes. ¿Puedes elevar el nivel de log o meter trazas para saber qué está pasando? Por otro lado veo que el ContentType es "text/plain" y debería ser "application/json"
me alegro de que ya esté funcionando !
Para ver los flags de compilación disponibles:
USER>Do $system.OBJ.ShowFlags()
See $system.OBJ.ShowQualifiers() for comprehensive list of qualifiers as flags have been superseded by qualifiers
b - Include sub classes.
c - Compile. Compile the class definition(s) after loading.
d - Display. This flag is set by default.
e - Delete extent.
h - Show hidden classes.
i - Validate XML export format against schema on Load.
k - Keep source. When this flag is set, source code of
generated routines will be kept.
l - Lock classes while compiling. This flag is set by default.
p - Percent. Include classes with names of the form %*.
r - Recursive. Compile all the classes that are dependency predecessors.
s - Process system messages or application messages.
u - Update only. Skip compilation of classes that are already up-to-date.
y - Include classes that are related to the current class in the way that
they either reference to or are referenced by the current class in SQL usage.
These flags are deprecated a, f, g, n, o, q, v
Default flags for this namespace
You may change the default flags with the SetFlags(flags,system) classmethod.Hola,
$SYSTEM.OBJ.CompileAllNamespaces() -- Compila las clases de TODOS los namespaces
Normalmente es más sencillo ir Namespace por Namespace (si hay varios) y se hace con $SYSTEM.OBJ.CompileAll(). Este método puede recibir "flags" de compilación. Yo suelo usar "ckub":
$SYSTEM.OBJ.CompileAll("ckub")Buscar/Reemplazar todo 17 mil veces... ¿qué puede salir mal?
Hola Mathew,
Siempre se puede hacer una clase que herede de %Persistent y que exponga los métodos que quieras para guardar por ejemplo. Internamente allí puedes crear tu Callback y luego llamar al %Save.
Algo así como:
Class MiPersistente Extends %Persistent {
Method OnGuardar() {
}
Method Guardar() {
..OnGuardar()
..%Save()
}
}Luego en lugar de heredar de %Persistent heredas de esta clase y sobre escribes el Callback.
No lo he probado pero es una alternativa a investigar
Gracias
Ja ja ja... que lo disfrutes con salud... manda foto de lo que te compres... si es que se puede ![]()
Esther no lo ha dicho pero los empleados de InterSystems lamentablemente no podemos participar... ![]()
Gracias por el aviso y por la nota Mario... siempre es útil este tipo de recomendaciones
Kurro dices que tu clase hereda de FTPService, si ves en el error la línea donde te da el error ¿es código tuyo o es código de la clase FTPService?
Enhorabuena a los ganadores!!
Como ya habéis visto vamos a hacer concurso cada mes, espero que os animéis a participar !!!
Cualquier duda sobre todo esto preguntad en la comunidad... estamos abiertos 24x7 ;-)
Hola @Fernando Iglesias de forma independiente a lo que responda Joel, creo que si creas un post con el problema concreto y todos los datos será más fácil que la comunidad pueda tener más información al respecto
Lo que @Kurro Lopez te ha presentado con detalle es lo que te decía en la primera respuesta:
También podría estar todo junto si no hay solapamiento entre nombres de paquetes y clases.
Como ellos ya lo han hecho han elegido la forma que mejor les ha funcionado. Por lo que desde luego es una buena solución.
El uso de mapeo de paquetes es util para no tener que duplicar clases (y código) en diferentes Namespaces. Pero es un mecanismo asociado a la operación/despliegue pero no al desarrollo. Son cuestiones diferentes. Puedo desarrollar un paquete de forma común y luego repartirlo entre varios namespaces (como una librería) o puedo ponerlo en un lugar accesible por varios (aka mapeo). Pero lo haga de una manera o de otra no me afecta a como lo desarrollo.
Bueno, el nombre correcto es Package Mapping, cierto que son paquetes lo que se mapea pero coloquialmente hablo de clases:
Sí claro, eso tiene mucho sentido. Lo único es que os toca gestionar varios Repos. Pero será muy práctico ir identificando funcionalidad común y llevarlo al Repo común. Luego las clases comunes gestionarlos como librerías independientes. Si el esquema que tenéis se despliega todo en la misma instancia entonces también podéis hacer mapeos de clases entre Namespaces.
Hola Jorge,
Me surgen varias dudas. Si trabajáis con diferentes Namespaces es porque son proyectos diferentes o ¿cómo están relacionados?. En principio lo lógico es que cada Namespace disponga de un Repo diferente. También podría estar todo junto si no hay solapamiento entre nombres de paquetes y clases. Ya que la idea es que cada desarrollador tenga un entorno aislado y por lo tanto el que toque clases de un Namespace normalmente no tocará las otras y esas no molestan. Sin embargo es muy importante que los despliegues en el servidor en producción se hagan de manera controlada y mediante paquetes de despliegue que se construyan ex-profeso para el mismo. No se si me he explicado bien...
Pero en resumen, una cosa es como se organiza el código en el desarrollo y otra diferente es como repartas las clases en el despliegue
Solo para dar alguna idea de que se podría enviar al concurso, echa un ojo a Rosetta Code - hay un montón de oportunidades de implementar esto u otros algoritmos populares que ya están implementados en otros lenguajes pero no en ObjectScript.
También le echaría un ojo a este articulo para saber como llamar correctamente al método:
Hola Laura, tendría que mirar como usar esa función, pero una cosa que siempre puedes hacer ya que te funciona en openSSL es llamar directamente a OpenSSL. Échale un ojo a este ejemplo https://github.com/drechema/ensemble-smime
Hola,
Yo te diría que no se dispone de esa característica directamente pero sin embargo es posible implementar algo similar de una manera muy eficiente mediante procedimiento almacenado en Object Script. Si envías un poco más de detalle del objetivo especifico podemos revisar y enviar algún ejemplo.
Gracias
Hola,
Gracias por preguntar.
Por lo que veo me parece que esto es un mensaje de MONMGR. Si es así este mensaje es generado por el Core y no por la para de Interoperabilidad así que ahora mismo el mecanismo es solo correo. Pero se me ocurre que pueden utilizar un servicio de lectura de correo y generar una alerta (Ens.Alert) que puedan manipular a su criterio. Aunque claro siendo una advertencia del correo es posible que haya procesos que se paren.
¿Cuál es el mensaje de error?
Este Post quizás también te puede ayudar:
https://community.intersystems.com/post/linked-stored-procedure-query-ensemble-201721