Import Java object in Typescript - java

To the downvoters - this is a legitimate question. Please take the time to examine it before assuming I'm mixing up my languages like some kind of programming newb!
I need to know if it's possible to import a Java object (specifically, an enum class) in a Typescript script.
I've googled but haven't found anything.
The ErrorCodeAuthority is for having custom, standardized errors thrown from our service for each known error with set messages (some parameterized, some not), http status codes, etc defined in one place.
In our javascript code we have
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
Is it possible to do the same in Typescript?
Edit based on answer below
I've declared the following:
declare module Java {
export enum ErrorCodeAuthority {
ENTITY_NOT_FOUND,
HTTP_VERB_NOT_SUPPORTED,
BAD_REQUEST,
//...
}
export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority;
export function type(arg: string): any;
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
and I'm attempting to use the new type as follows:
export class HttpFailResult extends HttpResult {
constructor(public errorCode : Java.ErrorCodeAuthority, public userParams? : UserParam[]) {
super(errorCode.httpStatus.value(), errorCode.toString());
}
}
I'm getting the following error when I try to use grunt to compile to js:
error TS2339: Property 'httpStatus' does not exist on type 'ErrorCodeAuthority'.
(For reference, the super HttpResult is an object that contains a number http code and astringbody. HttpStatus, in the Java enum, is of typeorg.springframework.http.HttpStatus`).
I tried removing the export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority; line but that didn't change the exception.
EDIT 2
We're running all of this inside a nashorn container if that makes a difference

Is it possible to do the same in Typescript?
Yes. With 1c, you can just write
let JavaErrorCodeAuthority = com.domain.ErrorCodeAuthority
And there will be auto-completion on each level of packages.

Yes, if you already did this in JavaScript you can use the code by creating a definition file for it and port it to TypeScript.
An example might be like this:
declare module Java {
export enum ErrorCodeAuthority {
item1,
item2
}
export function type(arg: "com.domain.ErrorCodeAuthority"): ErrorCodeAuthority;
export function type(arg: string): any;
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
The enum and the first type function with the "com.domain.ErrorCodeAuthority" is optional but it gives you better typeinfo when passed in that particular string. Note the declare module part doesn't generate any code and you can add it to a .ts or .d.ts file. More info about creating a definition file can be found here: https://github.com/Microsoft/TypeScript/wiki/Writing%20Definition%20Files
EDIT
after the info from the comments I hope this code below will better suite your need.
This has the downside that it isn't usable in a switch statement but in this case I think it is better to see the java enum as a module (or class was possible to). This might not be 100% correctly modelled but hopefully it gives you some extra idea's. Just a small side note, I find your case very interesting and challenging!
declare module Java {
interface ErrorCodeValue {
toString(): string;
value(): number;
}
module ErrorCodeAuthority {
var ENTITY_NOT_FOUND: IErrorCodeAuthority;
var HTTP_VERB_NOT_SUPPORTED: IErrorCodeAuthority;
var BAD_REQUEST: IErrorCodeAuthority;
}
interface IErrorCodeAuthority {
httpStatus: ErrorCodeValue;
}
export function type(arg: "com.domain.ErrorCodeAuthority"): typeof ErrorCodeAuthority;
export function type(arg: string): any;
}
export class HttpResult {
constructor(code: number, description: string) {
}
}
export class HttpFailResult extends HttpResult {
constructor(public errorCode: Java.IErrorCodeAuthority, public userParams? :any[]) {
super(errorCode.httpStatus.value(), errorCode.toString());
}
}
var JavaErrorCodeAuthority = Java.type("com.domain.ErrorCodeAuthority");
new HttpFailResult(JavaErrorCodeAuthority.BAD_REQUEST, null);

Related

Groovy StreamingTemplateEngine gives error with withCredentials function

I created the Jenkins pipeline which calls below function... It creates a Template variable with StreamingTemplateEngine object... But it gives an error
def call() {
def name = "abc"
def binding = [
firstname: "Grace",
lastname: "Hopper",
]
def text = 'Dear <% out.print firstname %> ${lastname}'
def template = new groovy.text.StreamingTemplateEngine().createTemplate(text)
print template.make(binding)
def response = template.make(binding)
withCredentials([string(credentialsId: 'Token', variable: 'TOKEN')]) {
println("test")
println(response)
}
}
Above code prints response successfully first time but at the end it gives below error
an exception which occurred:
in field com.cloudbees.groovy.cps.impl.BlockScopeEnv.locals
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv#3678d955
in field com.cloudbees.groovy.cps.impl.CpsClosureDef.capture
in object com.cloudbees.groovy.cps.impl.CpsClosureDef#23a3d63c
in field com.cloudbees.groovy.cps.impl.CpsClosure.def
in object org.jenkinsci.plugins.workflow.cps.CpsClosure2#6d8ad313
in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.closures
in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup#76f2b368
in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup#76f2b368
Caused: java.io.NotSerializableException: groovy.text.StreamingTemplateEngine$StreamingTemplate
If I remove withCredentials function then it works fine.
Jenkins Pipeline runs Groovy code in the continuation-passing style (groovy-cps). It expects that every local variable is Serializable so it can safely serialize every computation and restore it in case of, e.g., Jenkins restart.
In case of using a non-serializable object, Jenkins Pipeline offers #NonCPS annotation that can be used with a method to mark that this part of code is not serializable and shouldn't be transformed to the CPS code interpretation.
"Pipeline scripts may mark designated methods with the annotation #NonCPS. These are then compiled normally (except for sandbox security checks), and so behave much like “binary” methods from the Java Platform, Groovy runtime, or Jenkins core or plugin code. #NonCPS methods may safely use non-Serializable objects as local variables, though they should not accept nonserializable parameters or return or store nonserializable values. You may not call regular (CPS-transformed) methods, or Pipeline steps, from a #NonCPS method, so they are best used for performing some calculations before passing a summary back to the main script. Note in particular that #Overrides of methods defined in binary classes, such as Object.toString(), should in general be marked #NonCPS since it will commonly be binary code calling them."
Source: https://github.com/jenkinsci/workflow-cps-plugin#technical-design
You can extract StreamingTemplateEngine part to the separate #NonCPS method that expects a template as text, and a map of bindings. Something like this should be safe to use:
import com.cloudbees.groovy.cps.NonCPS
def call() {
def name = "abc"
def binding = [
firstname: "Grace",
lastname: "Hopper",
]
def text = 'Dear <% out.print firstname %> ${lastname}'
def response = parseTemplate(text, binding)
withCredentials([string(credentialsId: 'Token', variable: 'TOKEN')]) {
println(response)
}
}
#NonCPS
String parseTemplate(String text, Map bindings) {
new groovy.text.StreamingTemplateEngine().createTemplate(text)
.make(bindings)
.toString()
}

Calling methods between groovy scripts with correct parameters

I just started learning about groovy and trying to transpose my java code to groovy scripts. Usually java allows you have a class with only methods that you can call from other classes. I wanted to translate that to groovy. I have in one file - lets call it File1- a method like this:
def retrieveData(String name){
// do something
}
and in the second file, File2, I call File1 like this:
def file1Class = this.class.classLoader.parseClass(new File("../File1.groovy"))
and then try to call the method in File1 like this:
def data = file1Class.retrieveData("String")
but it keeps giving me this error - MissingMethodException:
groovy.lang.MissingMethodException: No signature of method: static File1.retrieveData() is applicable for argument types: (java.lang.String) values: [String] Possible solutions: retrieveData(java.lang.String)
so it does recognize that I am sending in the correct number of parameters and even the correct object, but it isn't running the method as it should?
Is there something I am missing? I tried to remove the object definition from the method - in other words - like this:
def retrieveData(name){
// do something
}
but that didn't work either. I am clueless about what the next step would be. Can anyone please help push me in the right direction? I would greatly appreciate it.
See the answer provided in this StackOverflow reponse.
Use the GroovyScriptEngine class. What does the GroovyScriptEngine do? From the docs:
Specific script engine able to reload modified scripts as well as
dealing properly with dependent scripts.
See the example below.
def script = new GroovyScriptEngine( '.' ).with {
loadScriptByName( '..\File1.groovy' )
}
this.metaClass.mixin script
retrieveData()
Note how we use the loadScriptByNamemethod to
Get the class of the scriptName in question, so that you can
instantiate Groovy objects with caching and reloading.
This will allow you to access Groovy objects from files however you please.

Import a Groovy script into another Groovy Script at Runtime

I have a Groovy file that looks like this (currently).
main.groovy
import org.packages.mystuff.JavaClassIAmUsing;
public class MyObject {
def rate(item){
def o = evaluate(new File (new File(getClass().protectionDomain.codeSource.location.path).parent),"CommonFunctions.groovy");
println o.whoami();
}
}
i have another groovy file called
CommonFunctions.groovy
def whoami() {return 'no body';}
I'm trying to include the CommonFunctions script in to main script, BUT the location of the script are not known at build time (i.e. i can not hardcode a absolute file path in the script or absoulte path of the java process in relation to where the scripts will be stored).
All i know is that the scripts will be together or at a location relative to the calling script (say sub directory).
I've attempted to try and location the calling script location, but i get the error
No signature of method: MyObject.evaluate()
How can i referance this script, considering the main script is accessed at runtime using a GroovyClassLoader.parseClass(File) method.
I'm not really sure why you want to do it this way, I think it would be much simpler to make a class of CommonsFunctions that you could instantiate normally and use everywhere.
However, it is possible to achieve what you want; with Groovy, there are not that many limitations...
There are two problems with your suggested solution:
getClass() inside your MyObject class naturally refers to ... the MyObject class, so your attempt to find the location of the script will fail. You're on the right track, but you need to resolve the script location using the surrounding Script class.
evaluate doesn't really work the way you think it does. The result of the evaluate method is the result of the script, not an instance of the Script class. One way to remedy this, is to rewrite the methods in CommonFunction as closure properties. These properties will be available in the shell Binding object when evaluating the script.
So, with these rewrites, you end up with something like this:
main.groovy
class MyObject {
def scriptDir
def rate(item) {
def commonFunctionsScriptFile = new File(scriptDir, "CommonFunctions.groovy")
def binding = new Binding()
new GroovyShell(binding).evaluate(commonFunctionsScriptFile)
println binding.variables.whoami()
}
}
scriptFile = new File(getClass().protectionDomain.codeSource.location.path)
new MyObject(scriptDir: scriptFile.parentFile).rate(null)
Here, the script file location is resolved in the script, not in the inner class.
CommonFunctions.groovy
whoami = { 'no body' }
Here, whoami is no longer a method, but a closure property which will be added to the binding. Make sure that you don't prefix this property with def, since then it will be a local variable instead of a property added to the binding object.
Output after these rewrites is the expected: no body.

GWT - impossible to find working dir with Eclipse

I need to show on my panel the working dir.
I use String value = System.getProperty("user.dir"). Afterwards i put this string on label but I receive this message on console:
The method getProperty(String, String) in the type System is not applicable for the arguments (String).
I use eclipse.
Issue
I am guessing you have not gone through GWT 101 - You cannot blindly use JAVA CODE on client side.
Explanation
You can find the list of classes and methods supported for GWT from JAVA.
https://developers.google.com/web-toolkit/doc/latest/RefJreEmulation
For System only the following are supported.
err, out,
System(),
arraycopy(Object, int, Object, int, int),
currentTimeMillis(),
gc(),
identityHashCode(Object),
setErr(PrintStream),
setOut(PrintStream)
Solution
In your case Execute System.getProperty("user.dir") in your server side code and access it using RPC or any other server side gwt communication technique.
System.getProperty("key") is not supported,
but System.getProperty("key", "default") IS supported, though it will only return the default value as there is not system properties per se.
If you need the working directory during gwt compile, you need to use a custom linker or generator, grab the system property at build time, and emit it as a public resource file.
For linkers, you have to export an external file that gwt can download and get the compile-time data you want. For generators, you just inject the string you want into compiled source.
Here's a slideshow on linkers that is actually very interesting.
http://dl.google.com/googleio/2010/gwt-gwt-linkers.pdf
If you don't want to use a linker and an extra http request, you can use a generator as well, which is likely much easier (and faster):
interface BuildData {
String workingDirectory();
}
BuildData data = GWT.create(BuildData.class);
data.workingDirectory();
Then, you need to make a generator:
public class BuildDataGenerator extends IncrementalGenerator {
#Override
public RebindResult generateIncrementally(TreeLogger logger,
GeneratorContext context, String typeName){
//generator boilerplate
PrintWriter printWriter = context.tryCreate(logger, "com.foo", "BuildDataImpl");
if (printWriter == null){
logger.log(Type.TRACE, "Already generated");
return new RebindResult(RebindMode.USE_PARTIAL_CACHED,"com.foo.BuildDataImpl");
}
SourceFileComposerFactory composer =
new SourceFileComposerFactory("com.foo", "BuildDataImpl");
//must implement interface we are generating to avoid class cast exception
composer.addImplementedInterface("com.foo.BuildData");
SourceWriter sw = composer.createSourceWriter(printWriter);
//write the generated class; the class definition is done for you
sw.println("public String workingDirectory(){");
sw.println("return \""+System.getProperty("user.dir")+"\";");
sw.println("}");
return new RebindResult(RebindMode.USE_ALL_NEW_WITH_NO_CACHING
,"com.foo.BuildDataImpl");
}
}
Finally, you need to tell gwt to use your generator on your interface:
<generate-with class="dev.com.foo.BuildDataGenerator">
<when-type-assignable class="com.foo.BuildData" />
</generate-with>

How can I convert OO Perl to Java?

I inherited large monolithic body of OO Perl code that needs to be gradually converted to Java (per client request). I know both languages but am rusty on my Perl skills. Are there any tools (Eclipse plugins?) that you folks can recommend to ease the pain?
Does OO code use Moose? If yes, it is possible to convert class declarations automatically using introspection.
To gradually convert Perl to Java, you can include Java code into Perl program with Inline::Java.
There is Perl on JVM project, maybe it can be used to compile Perl to Java?
I'd say PLEAC is one of the greatest resources.
The inccode.com allows you to automatically convert the perl code to java code. Nevertheless the conversion of perl variables is slightly tricky due to dynamic typing in perl. The scalar variable in perl can contain the reference to any type and the real referenced type is known when the code is executed.
Translator uses VarBox class for encapsulating all predefined types: ref(HASH), ref(ARRAY) and BoxModule for encapsulating the reference to Perl Modules.
The example show perl script which call two modules to print “hello world”. The module LibConsole is instantiated in script and the module LibPrinter is accessed by calling the method in LibConsole.
#!/usr/bin/perl
use strict;
use test::LibPrinter;
use test::LibConsole;
hello_on_console( "hello world");
hello_on_printer( "hello world");
sub get_console
{
my $console = test::LibConsole->new();
return $console;
}
sub get_printer
{
##cast(module="test::LibPrinter")
my $printer = get_console()->get_printer();
return $printer;
}
sub hello_on_console
{
my ($hello) = #_;
my $console = get_console();
$console->output ($hello);
}
sub hello_on_printer
{
my ($hello) = #_;
my $printer= get_printer();
$printer->output ($hello);
}
Translator must now the types of both modules and while perl don’t define specific operators for declaring the object there’s an assumption that method named “new” return the reference to module. When the method which return reference to module is named otherwise the annotation cast(module=”{class}”) can be used to inform translator about the type of the module.
The identified type of the variable will be propagate because the translator control the conformity of types in assignments.
public class hello extends CRoutineProcess implements IInProcess
{
VarBox call ()
{
hello_on_console("hello world");
return hello_on_printer("hello world");
}
BoxModule<LibConsole> get_console ()
{
BoxModule<LibConsole> varConsole = new BoxModule<LibConsole>(LibConsole.apply());
return varConsole;
}
BoxModule<test.LibPrinter> get_printer ()
{
BoxModule<LibPrinter> varPrinter = new BoxModule<LibPrinter>(get_console().getModule().get_printer());
return varPrinter;
}
VarBox hello_on_console (VarBox varHello)
{
BoxModule<LibConsole> varConsole = new BoxModule<LibConsole>(get_console());
return varConsole.getModule().output(varHello);
}
VarBox hello_on_printer (VarBox varHello)
{
BoxModule<LibPrinter> varPrinter = new BoxModule<LibPrinter>(get_printer());
return varPrinter.getModule().output(varHello);
}
}
The translated code requires runtime library to be executed.

Categories