Library Problems with Struts 2 Ajax JSON - json

I'm trying to have an Ajax call in my Struts 2 project in Netbeans, and I'm having issues getting it to work that seem to have to do with libraries. First of all, the only combination I've found that works at all is to use the current (2.5.22) JSON plugin with the Struts 2.3 core libraries; if I use the "correct" 2.3 version of the plugin, or if I use the 2.5 Struts libraries all around, I don't get any error messages, but I don't get any data either: none of the fields of the action class get populated. However, I can't get the return data back; instead I get an HTML-formatted 500 message saying "java.lang.NoClassDefFoundError: Could not initialize class org.apache.struts2.json.JSONResult" plus a ton of traceback after that. I can see perfectly well that this class is there in the JSON plugin jar. So my library list at present looks like this:
library list
My struts.xml entry for the action in question is
<action name="updateProductWorkforceAjax" class="prsm2.display.controller.SingleProductAjax"
method="updateProductWorkforceAjax">
<interceptor-ref name="json">
<param name="enableSMD">true</param>
</interceptor-ref>
<result type="json">
</result>
</action>
and I am extending the json-default package.
The Ajax call looks like this:
var arg = {dvList: dvlist,
prodId : prodId,
orgId : orgId,
programYear : programYear,
functionalArea : fa};
$.ajax({
data: arg,
type: 'POST',
dataType : 'json',
url: 'updateProductWorkforceAjax',
success: function(data) {
control.log(data);
},
error:function(result) {
var zz = result;
}
})
where all the variables folded into arg are strings. The action class has all the required getters and setters and appears to work fine-- after all if I use the inconsistent libraries, it gets data correctly.
I've tried using a complete set of libraries for one version, which will not run at all (the server won't even start).
If someone can tell me what libraries will work together for this, or what I'm doing wrong with the ones I have, I would appreciate it.

Related

In Angular, imported json file as indexed type always return undefined

You will find instructions to reproduce on your own device at the bottom.
I have a basic Angular project I created using Angular CLI, running on TypeScript 3.1.3, with nothing much added aside a class and a json file.
I created a class ResourcesService with the following command with Angular CLI:
ng generate service Resources
I'm basically using it to load json files, as a mean of localising (instead of using Angular unfinished builtin internationalisation features).
The following is my class, as well as the json file:
ResourcesBundle.json
{
"label.changeLanguage": "Change language",
"label.education": "Education",
"label.experience": "Experiences",
"label.skills": "Skills",
"label.summary": "Summary",
"label.language.english": "English",
"label.language.french": "French"
}
resources.service.ts
import * as resources from '../assets/resources/ResourcesBundle.json';
#Injectable({
providedIn: 'root'
})
export class ResourcesService {
constructor() {}
public getString(label: string): string {
let resource: string = resources[label];
return resource;
}
}
Of course, in order to be able to import the json file that way, I've set "resolveJsonModule": true in tsconfig.json.
The service by itself is working properly. I can inject it and call the getString method, and it's running without any error.
However, no matter what value I pass to the getString method, the returned value is always undefined. I've even tried to hard code the value for label = 'label.summary', but it's still returning undefined. The only time it's working properly is when I write the string directly between the brackets:
let resource: string;
label = 'label.summary';
resource = resources[label]; // resource == undefined
resource = resources['label.summary']; // resource == 'Summary'
Within the TS on VSCode, the content of resources is as following:
label.changeLanguage
label.education
label.experience
label.language.english
label.language.french
label.skills
label.summary
When using console.log(resources), the console was displaying something like this on Firefox:
Object {
label.changeLanguage: "Change language"
label.education: "Education"
label.experience: "Experience"
label.language.english: "English"
label.language.french: "French"
label.skills: "Skills"
label.summary: "Summary"
}
So the json is properly loaded, but it can only be used with hard coded string.
The only other solution I found was to give up the json file and initialise an indexed type directly in the code:
private resources: { [key: string]: string } = {
'label.changeLanguage': 'Change language',
'label.education': 'Education',
'label.experience': 'Experiences',
'label.skills': 'Skills',
'label.summary': 'Summary',
'label.language.english': 'English',
'label.language.french': 'French'
};
However, I don't think that's a good approach, at all...
In the case of the imported json file, why does it always return undefined when I use a variable? Or otherwise, why does it work only with a hard coded string between the brackets?
Edit:
You will find below a stackblitz link to a demo project:
https://stackblitz.com/edit/angular-h2aspf?file=tsconfig.json
If you run it on the browser, it will work properly (the console will properly display Change language).
However, if you download it and run it locally, you will notice that the console will display undefined instead.
To run it locally:
You must have npm and Angular CLI
Download and unzip the stackblitz demo in a folder
Run npm i in the project folder
Run ng serve --open
Open the console on your browser, it should be displaying undefined, instead of the expected value (Change language on stackblitz)
Edit:
According to a comment on the Angular CLI issue, a workaround is to set "esModuleInterop": true in tsconfig.json, and to change the import statement from:
import * as resources from '../assets/resources/ResourcesBundle.json';
To this:
import resources from '../assets/resources/ResourcesBundle.json';
Original answer:
After checking multiple times on different devices, I think this is a bug directly related to Angular (current version: 7.0.2).
To take the example I gave in the question again:
https://stackblitz.com/edit/angular-h2aspf?file=tsconfig.json
On the browser, this demo is outputting Change language on the console.
On locale device:
Download and unzip the stackblitz demo in a folder
Run npm i in the project folder
If you run with ng serve, you will notice undefined in the web browser console
Stop Angular, then run again with ng serve --prod. The web browser console is now properly outputting Change language
I've opened the following issues for Angular and Angular CLI projects on GitHub for this problem:
Angular: Issue #26785: Imported json file as indexed type always giving undefined when Angular is not running in production mode
Angular CLI: Issue #12781: Imported json file as indexed type always giving undefined, but not when running ng serve --prod

Cant get json4s data extraction to work

Im working on a project that has scala backend and scalatra as a servlet. For now, the backend is running inside a Vagrant box, and sbt is used to build the program.
My problem is that I need to handle incoming Json-formatted data, but I cant extract it properly - though I'm able to send Json data. First I played around with Scalas own Json parser, but realized that it's deprecated, so I had to find external library. After that I came up with json4s.
In my app I have the following endpoint listening for incoming post requests
post("/my/endpoint") {
// run the code in here
}
And that works just fine. I can put trivial println inside the brackets and it displays in the sbt shell after the endpoint has been called.
After that I defined a case class to be used to extract the data
case class Person(name : String) {
override def toString() = s"My name is $name"
}
And lastly I did the following code inside my endpoint function
post("/my/endpoint") {
val json = parse(request.body)
val person = json.extract[Person]
println(person)
}
So right now when calling the println it should print whatever the toString method of Person class returns, but it prints nothing.
Lets take a step back and modify the code so that we have the following
post("/my/endpoint") {
val json = parse(request.body)
println(json)
}
This piece of code prints the following into sbt shell
JObject(List((name,JString(joe))))
So we can see that the parse-function is actually doing something and data is being received.
But, if we add
person = json.extract[Person]
after println(json), the endpoint stops functioning. Why I think it's weird, is because it's not a compiling error, so everything before that line should work properly? Also it doesn't cause the program to crash on runtime, nor does it give any errors, warnings, etc. Every other endpoint and functions works still properly.
Also, I did try the example in json4s.org under the section 'Extracting values'.
I copied the code from word to word, but that did not work either.
Also FYI, my versions are SBT, 1.1.6, Scala 2.12.6, Scalatra 2.6.3, json4s 3.5.2 and Vagrant is using Xenial 16.04 as its basebox.
pls help mi

BlazeDS return DSK instead of AcknowledgeMessage

Hi I am trying to use a JS library to send and receive AS3 Objects. The library is this one: https://github.com/emilkm/amfjs. It works well but only when BlazeDS (3.5) returns AcknowledgeMessage messages that it can deserialize, if Blaze returns the Object as a DSK it chokes. The problem is BlazeDS is not being consistent on the type it returns for any given method, sometimes DSK sometimes AcknowledgeMessage (for the same method call, at some point during its up time it decides to return AcknowledgeMessage). The flex application handles this no problem, but how can I force Blaze to respond correctly?
To permanently turn off small messages add this following to the required channel in the services-config.xml. The properties node needs the following entry added for every channel you want to connect to using amf.js if you are going to have both Flex and HTML clientes from the same browser:
<properties>
<serialization>
<enable-small-messages>false</enable-small-messages>
</serialization>
</properties>

RazorEngine extension method fails with RuntimeBinderException after upgrade to Razor 2/ RE 3.2

I have a RazorEngine project that fails following an upgrade to Razor 2.0 and RazorEngine 3.2.0
This worked fine in the previous Razor 1.0 based version of RazorEngine (3.0.8).
I have an instance (myInstance) of a class (MyClass) and and extension method:
namespace MyCompany.Extensions
{
public static class MyClassExtensions
{
public static string ExtensionMethod(this MyClass thing)
{
// do stuff
}
}
}
I want to call this in a RazorEngine view (simplified example, there are loads of these methods, and all fail the same way):
#using MyCompany.Extensions
#using MyCompany
#{
var myInstance = new MyClass(Model, ...);
}
Some text #myInstance.ExtensionMethod() some more text
This is in a text file that's compiled by RazorEngine:
string parsedResult = RE::Razor.Parse(fileContent, myModel, "testfile.txt");
The problem is that this line (which used to work) throws a RuntimeBinderException:
'MyCompany.MyClass' does not contain a definition for 'ExtensionMethod'
Note that if I change the text file to:
Some text #MyClassExtensions.ExtensionMethod(myInstance) some more text
It works fine, so I think it must find the extension method's namespace.
My first thought was that it must be considering the passed model as a dynamic (and hence anything derived from it as dynamic too), but it knows the expected type in the RuntimeBinderException. As the exception is run-time I think it must be failing to identify the extension method while the template is compiled, but why would that have changed?
I'm not sure what's changed between 3.0.8 and 3.2.0, or why this is broken. Is there something I need to add so that the extension method can be found while the template is compiled?
This is a bug in RazorEngine: the Razor.Compile works on TemplateBase<dynamic> (so Model and everything derived from it is dynamic too) and that means that no extension methods undergo the 'compiler-magic' to convert them to the static calls. Then Razor.Run passes the Model as the correct type, but the extension method syntax is called as an instance method.
There will probably be a fix for this soon (the bug's only a few days old and this is a corner case), but in the meantime I have a workaround: explicitly type the Model in the Razor template
#using MyCompany.Extensions
#using MyCompany
#{
ExpectedModelClass strongTypeModel = Model as ExpectedModelClass;
MyClass myInstance = new MyClass(strongTypeModel , ...);
}
Some text #myInstance.ExtensionMethod() some more text
This now works, because even though Model is still dynamic at compile-time that doesn't spread to myInstance any more.
It's not ideal, and everywhere I used Model now has to be strongTypeModel, but that's a much simpler substitution.

Using JSON templates in Play 2.0

I'm getting this error:
Compilation error [package views.json.Runs does not exist]
when it clearly does exist. I can't figure out what I could be doing wrong.
the action in the Runs controller:
#BodyParser.Of(play.mvc.BodyParser.Json.class)
public static Result view(Long task_id, Long run_id) {
Run run = Run.find.byId(run_id);
return ok(views.json.Runs.view.render(run));
}
app/views/Runs/view.scala.json:
#(run: Run)
{
"started": "#run.started",
"completed": "#run.completed"
}
I've gotten a few html templates working, but this is the first JSON template I've tried with 2.0. I'm not sure what else to try since it's already about as basic as possible. Anyone have any ideas?
Update: I've gotten several suggestions for workarounds, but I'm still interested in knowing how to get the templates working, if only to better understand the changes to 2.0.
Only html, xml and txt appear to be supported by default. For other file extensions and formats, you'd have to register additional "templateTypes" in $PLAY_HOME/framework/src/sbt-plugin/src/main/scala/PlaySettings.scala (see also: SBT Settings, near the bottom).
It may be helpful to look at the standard template types definitions which are in $PLAY_HOME/framework/src/play/src/main/scala/play/api/templates/Templates.scala.
You could also cheat and serve your json from a txt file, but do response().setContentType("application/json") before calling the render method.
For Json, why don't you directly produce a Json string using the Json helper:
public static Result view(Long task_id, Long run_id) {
Run run = Run.find.byId(run_id);
return ok(play.libs.Json.toJson(run));
}
I recommend following the documentation and let the Json library serialize your data instead of writing the Json text on your own: See Serving Json Response.
I still don't understand, why does people want to render theirs JSON with views.
Note: this is the same way as #nico_ekito showed before and I agree with him totally , below code just demonstrates how to select part of the object for JSON
public static Result view(Long task_id, Long run_id){
Run run = Run.find.byId(run_id);
ObjectNode result = Json.newObject();
result.put("started", run.started);
result.put("completed", run.completed);
return ok(Json.toJson(result));
}