GridLauncher missing
🐛 Bug Report
The class org.openqa.grid.selenium.GridLauncherV4 does not exist. This makes us unable to use the parameters "-proxy" and "-servlets".
To Reproduce
Detailed steps to reproduce the behavior:
java -cp selenium-server-4.0.0-beta-2.jar org.openqa.grid.selenium.GridLauncherV4 -role node Error: Could not find or load main class org.openqa.grid.selenium.GridLauncherV4
Expected behavior
The class should exist.
Environment
OS: Windows 10 Selenium Grid version (if applicable): 4.0.0-beta2
Grid 4 is not compatible with Grid 3.
What is your use case?
Our implementation needs to be able to launch our customized proxy on the hub and servlets on the nodes.
Same here, in v3 there was a section in the proxy, before session and after session that was maintained throughout the iterations and could be used to prep the node before the test starts like starting/stopping a video recording.
Where in the v4 code can we do this?
No movement on this in 6 months? This is a serious loss of functionality. @diemol @titusfortner
What does your customized proxy do? That reply was very ambiguous.
The customized proxy does various work inside the proxy class methods (eg. beforeSession, afterSession, etc.).
This includes things to prepare the node for use before the test starts, like killing rogue processes.
The custom servlet is similar, allowing us to run commands on the nodes from inside tests.
To alter the behaviour of a session, you need to provide a Node implementation. The default one is the LocalNode, which serves as a good template to build from there. An example of that is the OneShotNode.
You can provide the implementation through the --node-implementation flag.
Thanks for this pointer, @diemol .
However, it doesn't work. If I include the --node-implementation flag in the command, the node doesn't launch.
It just prints the help:
>java -jar selenium-server-4.1.2.jar --node-implementation SuperNode node
Selenium Server commands
A list of all the commands available. To use one, run `java -jar selenium.jar
commandName`.
[...]
https://www.selenium.dev/documentation/grid/getting_started/
The arguments are in the wrong order, also you would need to share the class path.
I don't see anything in that link that defines an order for arguments.
And what do you mean by share the class path ?
This is an example that shows how a Node is started https://www.selenium.dev/documentation/grid/getting_started/#nodes and you add the parameters after that:
java -jar selenium-server-4.1.2.jar node --node-implementation SuperNode
The class path the same way you were doing it java -cp
Ok, using this modified command:
java -cp . -jar selenium-server-4.1.2.jar node --node-implementation SuperNode
Generates this ClassNotFoundException:
09:42:16.126 INFO [LogManager$RootLogger.log] - Using the system default encoding
09:42:16.129 INFO [OpenTelemetryTracer.createTracer] - Using OpenTelemetry for tracing
09:42:16.683 INFO [UnboundZmqEventBus.<init>] - Connecting to tcp://0.0.0.0:4442 and tcp://0.0.0.0:4443
09:42:16.738 INFO [UnboundZmqEventBus.<init>] - Sockets created
09:42:17.751 INFO [UnboundZmqEventBus.<init>] - Event bus ready
09:42:18.548 INFO [NodeServer.createHandlers] - Reporting self as: http://10.12.73.121:5555
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.openqa.selenium.grid.Bootstrap.runMain(Bootstrap.java:77)
at org.openqa.selenium.grid.Bootstrap.main(Bootstrap.java:70)
Caused by: org.openqa.selenium.grid.config.ConfigException: java.lang.ClassNotFoundException: SuperNode
at org.openqa.selenium.grid.config.MemoizedConfig.getClass(MemoizedConfig.java:115)
at org.openqa.selenium.grid.node.config.NodeOptions.getNode(NodeOptions.java:148)
at org.openqa.selenium.grid.node.httpd.NodeServer.createHandlers(NodeServer.java:127)
at org.openqa.selenium.grid.node.httpd.NodeServer.asServer(NodeServer.java:183)
at org.openqa.selenium.grid.node.httpd.NodeServer.execute(NodeServer.java:230)
at org.openqa.selenium.grid.TemplateGridCommand.lambda$configure$4(TemplateGridCommand.java:129)
at org.openqa.selenium.grid.Main.launch(Main.java:83)
at org.openqa.selenium.grid.Main.go(Main.java:57)
at org.openqa.selenium.grid.Main.main(Main.java:42)
... 6 more
Caused by: java.lang.ClassNotFoundException: SuperNode
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.openqa.selenium.grid.config.ClassCreation.callCreateMethod(ClassCreation.java:35)
at org.openqa.selenium.grid.config.MemoizedConfig.lambda$getClass$4(MemoizedConfig.java:100)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source)
at org.openqa.selenium.grid.config.MemoizedConfig.getClass(MemoizedConfig.java:95)
... 14 more
Exception in thread "Thread-1" java.lang.NullPointerException
at org.openqa.selenium.grid.node.httpd.NodeServer.lambda$new$0(NodeServer.java:79)
at java.lang.Thread.run(Unknown Source)
But where did you package the overloaded class? In a jar? Why are you not putting the whole class name?
That is the whole class name. The file SuperNode.class is in the current directory when running the command to start the node.
Ok, so a more concrete example. We have the OneShotNode, and to use that, we generate a jar that contains the class and the jar is called libk8s.jar.
We added a flag that lets you add that jar in a more simple way, no class path commands needed. The command will look like this:
java -jar selenium-server-4.1.2.jar --ext libk8s.jar node --node-implementation org.openqa.selenium.grid.node.k8s.OneShotNode
Even if the class is called OneShotNode, I need to put the whole class name: org.openqa.selenium.grid.node.k8s.OneShotNode
I was able to build a jar that allows the node to attempt to start, but it throws an exception when trying to read the configuration information:
Caused by: org.openqa.selenium.grid.config.ConfigException: Unable to find node stereotype
at nthrive.SuperNode.lambda$create$0(SuperNode.java:112)
This code block appears to be at fault:
Map<String, Object> raw = new Json().toType(
config.get("k8s", "stereotype")
.orElseThrow(() -> new ConfigException("Unable to find node stereotype")),
MAP_TYPE);
How do I have to modify this to read a standard toml config file?
Seems you are copying the exact same code from OneShotNode, where that configuration field is needed.
Feel free to strip down things that you do not need for your purpose. Also, you can use LocalNodeFactory and LocalNode as guides too.
Is LocalNode the class that is used for nodes when a grid is started without options? (java -jar server.jar) ?
I was able to hack the code to get around the previous error, but it appears the custom class is not being used, as my added logging statements don't show up in the node log file.
Everything we've discussed so far only relates to the -proxy parameter that was lost. Where's the replacement for the -servlet parameter?
We did not implement ways for servlets, and in most cases it could be also done in a proxy. What servlet cases do you have in mind?
We were using the servlets to create callable endpoints on the hub, e.g.:
http://hub:4444/grid/admin/tasklist?sessionId=12345
So that when these endpoints were hit, we could execute some custom code in response inside of the servlet's process method:
protected void process(HttpServletRequest request, HttpServletResponse response) throws IOException
@diemol will there be support for servlets in Se 4?
We can have a look at that based on community feedback. So far, the need for it seems to be very low, and therefore is low priority. Obviously, if someone wants to give us a hand implementing that, we are open to collaborate.
We have been discussing this (Proxy and Servlet) for Grid 4 in the team, and so far we see:
- Proxy: can be done by providing a
Nodeimplementation. - Servlets: Use cases point to admin tasks done in the server. That type of work can be done outside the Grid server, implemented in any language/framework.
Are there any other use cases that would require to have Servlets supported again? Looking forward to your feedback.
Very glad to hear this is still under consideration.
I have not been able to find a way to create a custom "Node implementation" that works. If you have a working example, I'd love to see it.
As to servlets, our use was to be able to send a command to the hub to be executed or to be forwarded to a node for execution. e.g. to find out whether a specific process is running on the node, etc.
Very glad to hear this is still under consideration.
Not exactly being considered for development at the moment. We are open to hear use cases for Servlets that need to be inside the Grid for them to work properly.
Regarding the Node implementation, I will add something to the docs to make it clear.
Hello
from what I've seen, it's not possible do add routes to node / hub, so I ended up using a node-implementation that creates a servlet server, but it's not ideal as from my grid client, I need to adress servers, depending on the action performed
An example on a detailed node inplementation would be great
@bhecquet : Any chance you could share some of your implementation? What are you using to run servlets, and what command are you using to launch your custom node?
@ccarmannt : you can look at my custom grid: https://github.com/bhecquet/seleniumRobot-grid/tree/selenium4 Especially
- for servlets on node: https://github.com/bhecquet/seleniumRobot-grid/blob/selenium4/src/main/java/com/infotel/seleniumrobot/grid/node/SeleniumRobotNodeFactory.java
- for servlets on hub/router: https://github.com/bhecquet/seleniumRobot-grid/blob/selenium4/src/main/java/com/infotel/seleniumrobot/grid/GridStarter.java#L443
Servlet server is started on router / node port + 10 so it's not pretty, but it works :)
If you have any question, I will be happy to reply
@bhecquet : thanks for this. Much appreciated.
Closing since, thanks to @krmahadevan, we have now documentation that shows how to create your own Node.