Server-side rendering of Java, ReactJs code on a web browser - javascript

What do I need to do to render this on browser? The code below currently works and renders on Eclipse Console. I need to use this code with a server like Tomcat and display it on browser with localhost. Please advice.
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.FileReader;
public class Test {
private ScriptEngine se;
// Constructor, sets up React and the Component
public Test() throws Throwable {
ScriptEngineManager sem = new ScriptEngineManager();
se = sem.getEngineByName("nashorn");
// React depends on the "global" variable
se.eval("var global = this");
// eval react.js
se.eval(new FileReader("../react-0.14.7/build/react.js"));
// This would also be an external JS file
String component =
"var MyComponent = React.createClass({" +
" render: function() {" +
" return React.DOM.div(null, this.props.text)" +
" }" +
"});";
se.eval(component);
}
// Render the component, which can be called multiple times
public void render(String text) throws Throwable {
String render =
"React.renderToString(React.createFactory(MyComponent)({" +
// using JSONObject here would be cleaner obviously
" text: '" + text + "'" +
"}))";
System.out.println(se.eval(render));
}
public static void main(String... args) throws Throwable {
Test test = new Test();
test.render("I want to Display");
test.render("This on a Browser like google chrome, using Tomcat server with Eclipse, currently it displays on Console in Eclipse.");
}
}

Many possibilities are there. One quite commonly used will be to go for REST services. You can host REST services using JAX-RS or Spring REST support. Put your web pages as a simple html page. Once this page will be loaded, it will make a REST call, will get the data and will show it to the user.

You can use JSP to do that..
Create a JSP page. Import the Test class.
You can check http://www.tutorialspoint.com/articles/run-your-first-jsp-program-in-apache-tomcat-server to know how to use JSP.

Related

Getting access to non-public files from Laravel 8 storage folder with JS

I'm in the following scenario:
Laravel 8 app.
Storing by the user uploaded STL files in the storage/app/users/{userid} folder.
STLs are private and may not be located in public folder and thus may not be accessible for everyone.
Now I'm trying to get access to these private STL files through javascript to load them in my Three.js scene for viewing.
My problem is: If I try to get the filepath from the database beforehand by using the storage_path() function in my Laravel controller and then pass this filepath (e.g. locally: /Users/Leon/MyLaravelApp/storage/app/users/1/file.stl) into my Three.js STLLoader function:
import * as THREE from 'three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
// {...}
let THREE_loader = new STLLoader();
let THREE_geometry;
THREE_loader.load(filePath, function (geometry) {
THREE_geometry = geometry;
// {...}
});
I - of course - get the error message 404 every time I try it, because the given path is relative to my web root and therefore not correct!
[Error] Failed to load resource: the server responded with a status of
404 (Not Found)
http://127.0.0.1:8000/Users/Leon/MyLaravelApp/storage/app/users/1/file.stl
Now my question is:
Is there any possible way to get around this problem? How can i access private files (not in the public folder) from javascript in my Laravel 8 app? There has to be a solution to this right?
Other solutions I thought about:
Storing the files directly in the database -> files too large?!
Storing an "safe" encrypted filepath of the file inside the public(!) folder in the database -> not safe enough?!
But both of these "solutions" are definitely not one of my favorites!
Maybe someone could point me in the right direction? 🤔
Best regards, Leon
The solution I came up with over time:
Generally:
To get access to private files I figured that you must have some kind of special web route for that with some kind of FileController at the end which checks if you have permission to view the file and then decides to either abort() or otherwise return the file itself with a FileResponse.
Laravel (my case):
JS
import * as THREE from 'three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
let THREE_loader = new STLLoader();
let THREE_geometry;
THREE_loader.load('data/users/1/filename.stl', function (geometry) {
THREE_geometry = geometry;
// {...}
});
PHP (web route)
<?php
use App\Http\Controllers\File\FileController;
use Illuminate\Support\Facades\Route;
Route::get('data/users/{user_id}/{filename}', [FileController::class, 'load_user_stl']);
PHP (FileController)
<?php
namespace App\Http\Controllers\File;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Response;
class FileController extends Controller
{
public function load_user_stl($user_id, $filename): \Illuminate\Http\Response
{
if (str_contains($filename, '.stl')) {
if (Gate::allows('access-user-stl') || Auth::id() == $user_id) {
return $this->return_user_stl($user_id, $filename);
} else {
abort(403);
}
} else {
abort(400);
}
}
public function return_user_stl($user_id, $filename): \Illuminate\Http\Response
{
$path = storage_path('app/data/users/'.$user_id.'/'.$filename);
try {
$file = File::get($path);
$type = File::mimeType($path);
$response = Response::make($file);
$response->header('Content-Type', $type);
return $response;
} catch (FileNotFoundException) {
abort(404);
}
}
}
Hope I could help you somehow and if somebody has an even cleaner way let me know:)
Leon

Adding a javascript file to an already-running Java FX webengine

I have a Java application that is running a Java FX webengine (the end goal of all of this is to dynamically draw a D3.js plot). I'd like to be able to add new javascript files to it while it's already running, and then ideally unload them again when the javascript tells it to.
This has the effect of making some functionality available to the user or not (drawing certain features) without having to load all of the code in at once. It also helps me avoid future headaches with a forest of brittle if/then statements inside my javascript.
Question 1: Is "unloading" files from a running webengine even possible? At least, possible without redrawing the whole thing. I'm pretty sure that calling loadContent() with my new filepaths will make them available the way that I want, but I haven't come across anything talking about how you can remove existing source code from your HTML block.
Question 2: Any recommendations on how to elegantly approach feeding the extra sources into the webView? My thought process right now is stuck on brute force, but I haven't been even been able to brute force my way to a solution that works, so maybe I'm barking up the wrong tree.
Question 3: Is this even a good idea? It's possible to do this solely in the Javascript, but I want the appearance and disappearance of options directly tied to a java-side feature that's later going to be executed from the class Bridge, the same place I'm trying to load new content from right now.
I asked a lot of questions, but any help is appreciated!
Right now I am setting up the webengine's content like so:
final ResourceExtractor RESOURCE_EXTRACTOR
= new ResourceExtractor(JavaScriptPlot.class);
// prepare the local URI for d3.js
final URI D3_JS_URI = RESOURCE_EXTRACTOR
.extractResourceAsPath("d3.min.js")
.toUri();
// prepare the local URI for numeric.js
final URI NUMERIC_JS_URI = RESOURCE_EXTRACTOR
.extractResourceAsPath("numeric.min.js")
.toUri();
// prepare the local URI for topsoil.js
final URI TOPSOIL_JS_URI = RESOURCE_EXTRACTOR
.extractResourceAsPath("topsoil.js")
.toUri();
// build the HTML template (comments show implicit elements/tags)
HTML_TEMPLATE = (""
+ "<!DOCTYPE html>\n"
// <html>
// <head>
+ "<style>\n"
+ "body {\n"
+ " margin: 0; padding: 0;\n"
+ "}\n"
+ "</style>\n"
// </head>
+ "<body>"
+ "<script src=\"" + D3_JS_URI + "\"></script>\n"
+ "<script src=\"" + NUMERIC_JS_URI + "\"></script>\n"
+ "<script src=\"" + TOPSOIL_JS_URI + "\"></script>\n"
+ "<script src=\"%s\"></script>\n" // JS file for plot
// </body>
// </html>
+ "").replaceAll("%20", "%%20");
The source path to replace %s is created here:
public class BasePlot extends JavaScriptPlot {
private static final ResourceExtractor RESOURCE_EXTRACTOR
= new ResourceExtractor(BasePlot.class);
private static final String RESOURCE_NAME = "BasePlot.js";
public BasePlot() {
super(
RESOURCE_EXTRACTOR.extractResourceAsPath(RESOURCE_NAME),
new BasePlotDefaultProperties());
}
}
And then later I take a file path already extracted as a resource, sourcePath, and insert it into the HTML block:
String buildContent() {
return String.format(HTML_TEMPLATE, sourcePath.toUri());
}
Then I build my web view using the return value of buildContent()
private void initializeWebView() {
runOnFxApplicationThread(() -> {
// initialize webView and associated variables
webView = new WebView();
webView.setContextMenuEnabled(false);
WebEngine webEngine = webView.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(
(observable, oldValue, newValue) -> {
if (newValue == SUCCEEDED) {
if (new IsBlankImage().test(screenCapture())) {
webEngine.loadContent(buildContent());
}
topsoil = (JSObject) webEngine.executeScript("topsoil");
topsoil.setMember("bridge", new Bridge());
}
});
// asynchronous
webEngine.loadContent(buildContent());
});
}
And the Javascript can fire off the method in the class below to trigger the change. Right now it's manually creating a hardcoded resource, but once I work out once going wrong I'll make this part more elegant/logically organized.
//loads appropriate JS files into webview based on BasePlot's isotope type
public class Bridge {
final URI ISOTOPE_URI = ISOTOPE_RESOURCE_EXTRACTOR
.extractResourceAsPath("Concordia.js")
.toUri();
String finalHtml = buildContent().concat("<script src=\""+ISOTOPE_URI.toString()+"\"></script>\n");
webView.getEngine().loadContent(finalHtml);
}
}
The loadContent() above is giving me an application thread error: "ReferenceError: Can't find variable: topsoil"

Running an Executable file from an ASP.NET web application

I am trying to create a web application that can read certain files (logs) provided by the users and then Use the LogParser 2.2 exe by microsoft to parse the logs and provide the requested output.
The idea i have is to run the Local LogParser.exe present in the Users system and then use the same generated output to ready my output.
I don not know if this approach is correct , However i am trying to do the same and somewhere my code is not correctly being followed and i am not able to find any output/Error .
My code segment is as follows :
protected void Button2_Click(object sender, EventArgs e)
{
try
{
string fileName = #"C:\Program Files (x86)\Log Parser 2.2\LOGPARSER.exe";
string filename = "LogParser";
string input = " -i:IISW3C ";
string query = " Select top 10 cs-ur-stem, count(cs-ur-stem) from " + TextBox1.Text + " group by cs-uri-stem order by count(cs-ur-stem)";
string output = " -o:DATAGRID ";
string argument = filename + input + query + output;
ProcessStartInfo PSI = new ProcessStartInfo(fileName)
{
UseShellExecute = false,
Arguments = argument,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = false
};
Process LogParser = Process.Start(PSI);
LogParser.Start();
}
catch (Exception Prc)
{
MessageBox.Show(Prc.Message);
}
I might be doing something wrong , but can someone point me in correct direction ? Can Javascript ActiveX control may be the way forward ?
All the help is appreciated
(( I am making it as an internal application for my organisation and it is assumed that the log parser will be present in the computer this web application is being used )0
Thanks
Ravi
Add a reference to Interop.MSUtil in your project and then use the COM API as described in the help file. The following using statements should allow you to interact with LogParser through your code:
using LogQuery = Interop.MSUtil.LogQueryClass;
using FileLogInputFormat = Interop.MSUtil.COMTextLineInputContextClass;
Then you can do something like:
var inputFormat = new FileLogInputFormat();
// Instantiate the LogQuery object
LogQuery oLogQuery = new LogQuery();
var results = oLogQuery.Execute(yourQuery, inputFormat);
You have access to a bunch of predefined input formats and output formats (like IIS and W3C)), so you can pick the one that best suits your needs. Also, you will need to run regsvr on LogParser.dll on the machine you are executing on if you have not installed LogParser. The doc is actually pretty good to get you started.

Dynamic Templates for CKEditor

I've got CKEditor embedded on a UserControl in our web application. All works fine with loading the default templates for CKEditor, on my local machine and our server.
I'm fetching templates from a database table, transforming the results to the appropriate JSON format and then writing that to a javascript file to add to CKEDITOR.template_files.
An example of the js content I'm generating in the js file:
CKEDITOR.addTemplates('templateskey',{imagesPath:'',templates:[{title:'LCH - Complaint', image:'', description:'Message Template - Complaints', html:'HtmlContent'}]});
Now my problem is that on our server my dynamically created js file seems to get blocked since it's supposed to load over HTTPS. Either this or my file can't be found.
[blocked] The page at 'https://...' was loaded over HTTPS, but ran
insecure content from 'http://...' (page not found url): this content
should also be loaded over HTTPS.
After this CKEDITOR.config tries to load the "templatesKey" template and fails to do so with:
Uncaught TypeError: Cannot read property 'imagesPath' of undefined
I've downloaded the ASP.Net version of CKEditor and included the project in my solution. I'm setting myCKEditor.TemplatesFiles and myCKEditor.Templates in the code behind:
myCKEditor.TemplatesFiles = "['" + relativePath + "']";
myCKEditor.Templates = "templateskey";
Is the problem that I'm generating the js file dynamically? Or is the problem that the templates plugin is loading content over HTTP rather than HTTPS? Is there a better way to dynamically add templates to CKEditor?
So talking to my friend that has expertise in SSH and HTTPS. This might be a limitation on HTTPS since I'm generating content dynamically it sees the content as a possible threat and unsecure.
CkEditor - Template loaded from AJAX is a good solution to the problem.
If you're working with ASP .Net you can build a Handler. Call the handler with ajax and pass JSON back.
e.g. The handler:
//Implement IRequiresSessionState is you want anything from the session state
public class TemplateHandler : IHttpHandler, IRequiresSessionState
{
/// <summary>
/// You will need to configure this handler in the Web.config file of your
/// web and register it with IIS before being able to use it. For more information
/// see the following link: http://go.microsoft.com/?linkid=8101007
/// </summary>
#region IHttpHandler Members
public bool IsReusable
{
// Return false in case your Managed Handler cannot be reused for another request.
// Usually this would be false in case you have some state information preserved per request.
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
try
{
//write your handler implementation here.
string ID = Convert.ToString(context.Session["ID"]);
DataSet dsTemplates = ExecuteStoredProc("uspTemplateRead");
if (!dsTemplates.ContainsData())
return;
List<Template> templates = new List<Template>();
foreach (DataRow row in dsTemplates.Tables[0].Rows)
{
Template template = new Template();
template.Title = row["Title"].ToString();
template.Image = "template.gif";
template.Description = row["Descr"].ToString();
template.Html = row["Temp"].ToString();
templates.Add(template);
}
byte[] b;
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(List<Template>));
using (MemoryStream stream = new MemoryStream())
{
jsonSerializer.WriteObject(stream, templates);
b = stream.ToArray();
}
context.Response.Clear();
context.Response.ContentType = "application/json";
context.Response.AddHeader("Content-Length", b.Length.ToString());
context.Response.BinaryWrite(b);
context.Response.Flush();
}
catch (Exception ex)
{
throw ex;
}
}
}
And then the Ajax call:
CKEDITOR.on("instanceReady", function () {
try {
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function () {
var json;
if (this.responseText == "")
json = "";
else
json = JSON.parse(this.responseText);
var template = {
imagesPath: CKEDITOR.getUrl(CKEDITOR.plugins.getPath("templates") + "templates/images/"),
templates: json
};
CKEDITOR.addTemplates('myTemplates', template);
};
httpRequest.open('GET', '/handlers/templatehandler.ashx');
httpRequest.send();
} catch (ex) {
console.log(ex);
}
});

Extending Selenium RC with new methods

I am extending the selenium RC by using user-extension.js.
It is able to call the new method function, but throwing following error message.
*ERROR: Command execution failure. Please search the forum at http://clearspace.openqa.org for error details from the log window.
The error message is: Object doesn't support this property or
method*
As this program is executed on Google.com, any one can copy the sample code and execute on their respective PCs.
package package1;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.*;
import com.thoughtworks.selenium.*;
public class Sample2
{
private static final String Timeout = "30000";
private static final String BASE_URL = "http://google.com/";
private static final String BASE_URL_1 = "/";
private Selenium selenium;
private HttpCommandProcessor proc;
#BeforeClass
protected void setUp()throws Exception
{
proc = new HttpCommandProcessor("localhost", 4444, "*iexplore", BASE_URL);
selenium = new DefaultSelenium(proc);
selenium.start();
selenium.windowFocus();
selenium.windowMaximize();
selenium.windowFocus();
}
#AfterClass(alwaysRun=true)
protected void tearDown() throws Exception
{
selenium.stop();
}
#Test(groups="search")
public void test_GoogleSearch() throws Exception
{
selenium.open(BASE_URL_1);
selenium.type("name=q", "Bharath Marrivada");
//selenium.click("btnG");
proc.doCommand("myMethod",new String[] {"btnG"}); //user extension
Thread.sleep(5000);
}
}
user-extension.js
Selenium.prototype.doMyMethod = function(inputParams)
{
this.browserbot.click("btnG");
return null;
};
.js and Selenium JAR are in the same folder and executing the Selenium JAR using following command.
java -jar selenium-server.jar -userExtensions user-extensions.js
Any help on this issue?
It means that your command in user-extension file is not locating the element. Try running that in the IDE and check if it works fine
It works for me. Here is the modified user-extensions.js file code:
Selenium.prototype.doMyMethod = function(locator) {
var element = this.page().findElement(locator);
element.click();
};
Rest all remains the same. Hope this helps!!!

Categories

Resources