Jetty Server not Working for War with JSPs - jetty

I am trying to create a simple jetty server/container that will take a war file and deploy. This is not embedded jetty with spring-boot.
Here is my build.gradle dependencies:
dependencies {
def jettyVersion = "9.4.34.v20201102"
implementation "org.eclipse.jetty:jetty-server:$jettyVersion"
implementation "org.eclipse.jetty:jetty-security:$jettyVersion"
implementation "org.eclipse.jetty:jetty-servlet:$jettyVersion"
implementation "org.eclipse.jetty:jetty-webapp:$jettyVersion"
implementation "org.eclipse.jetty:jetty-annotations:$jettyVersion"
implementation "org.eclipse.jetty:jetty-jmx:$jettyVersion"
}
Here is my main class:
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
MBeanContainer mbContainer = new MBeanContainer(getPlatformMBeanServer());
server.addBean(mbContainer);
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar(warFile()); // LOGIC TO UPLOAD WAR FILE
webapp.setExtractWAR(true);
Configuration.ClassList classList = Configuration.ClassList.setServerDefault(server);
classList.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
"org.eclipse.jetty.annotations.AnnotationConfiguration");
webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");
server.setHandler(webapp);
server.start();
server.dumpStdErr();
server.join();
}
However, when I try to go to the app (http://localhost:8080/index), I keep getting the following error message:
URI: /index
STATUS: 500
MESSAGE: JSP support not configured
SERVLET: jsp
There is only one line of error message in the console:
2020-12-11 09:49:51.563:INFO:oejshC.ROOT:qtp2025864991-33: No JSP support. Check that JSP jars are in lib/jsp and that the JSP option has been specified to start.jar
What JSP Jars that it is referring to? I am at a loss as to what dependencies I need to add to make it work for JSPs.
Thx.

You will have to add apache-jsp so that your server will support jsps. If your web app uses jstl, you should also add apache-jstl.

For WebAppContext usage (which is a bit easier to setup than ServletContextHandler usage) you'll need the following artifacts ...
https://search.maven.org/artifact/org.eclipse.jetty/apache-jsp (for the Jetty specific JettyJspServlet which extends from the Jasper JspServlet)
https://search.maven.org/artifact/org.eclipse.jetty/apache-jstl (to support Taglibs custom and standard)
Make sure your org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern can reference the apache-jsp artifact properly, otherwise the internal javax.servlet.ServletContextInitializer will not load properly.
If nothing happens by simply adding those artifacts, you'll need to verify your default descriptor setup on your WebAppContext.setDefaultsDescriptor(String) to ensure that you pass in a resource reference (path or uri) to the Jetty default descriptor XML.
https://github.com/eclipse/jetty.project/blob/jetty-9.4.35.v20201120/jetty-webapp/src/main/config/etc/webdefault.xml
Enabling JSP support in embedded mode can be quite tricky if you use the ServletContextHandler instead of the WebAppContext.
If you ever decide to use the ServletContextHandler instead of a WebAppContext (to have a single fat/uber jar, to speed up load/deploy time, to ease unit testing, etc...), then check out the Jetty maintained example project at ...
https://github.com/jetty-project/embedded-jetty-jsp

Related

How to bring SOAP capability to payara/micro in EJB project

I have an EJB project providing webservices (both SOAP and REST) running inside a container with payara/micro as base image, since payara/micro does not come with JAXWS(SOAP support) feature out of the box, however, by adding
cxf-rt-frontend-jaxws
and
cxf-rt-transports-http
as dependencies into the project as well as following this tutorial and put the following code instead:
#Override
public void loadBus(ServletConfig servletConfig) {
super.loadBus(servletConfig);
Bus bus = getBus();
BusFactory.setDefaultBus(bus);
Endpoint.publish("/MySoapService", new ASoapService());
}
I was able to make the SOAP interface almost available (wsdl information is publicly available already), and
http://localhost:8080/<my project name>/services
event listed out the available services as well their available methods and endpoints/WSDL/Target namespace information.
But when trying to access the SOAP service via SOAP client, I got on the server side errors with the following line of info:
...
Caused by: java.lang.NullPointerException: null
at com.example.ASoapService.getXxx
...
Where
ASoapService
Is Actually an EJB. So I tried instead to replace the above code with the following:
#EJB
ASoapService aSoapService
...
Endpoint.publish("/MySoapService", aSoapService);
During startup of container, I got
Caused by: javax.naming.NameNotFoundException: com.example.ASoapServiceF#com.example.ASoapService not found
By checking the logs, I found a possible reason:
When SOAP part starts up with the following code
Endpoint.publish("/MySoapService", aSoapService);
The EJB Container is not yet ready and thus the lookup of
ASoapService
failed, is such assumption correct? Because normally you should see something like:
[2018-02-02T14:43:57.821+0000] [] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1517582637821] [levelValue: 800] Portable JNDI names for EJB ASoapService: [java:global/<my project name>/ASoapService, java:global/<my project name>/ASoapService!com.example.ASoapService]
during start up, which is not the case for my situation.
I am relatively new to EJB and Glassfish world, can I somehow force EJB container to start first? Or does it actually have anything to do with the starting sequence? How to combine the two together?
Thanks in advance.
You shouldn't be trying to force EJB container to start. Instead, try one of the following:
instead of #EJB ASoapService aSoapService to inject the EJB try #Inject
ASoapService aSoapService - #Inject should wait for the dependencies therefore wait until the EJB is available
run the method Endpoint.publish from an object which is initialized after EJB container is ready, either from a startup singleton EJB or when CDI application scope is initialized: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/

embedded jetty ignoring classes packaged in my war

I'm trying to run jetty in embedded mode. It appears to be ignoring all the classes bundled in my war file, whether under WFB-INF/classes or WEB-INF/lib.
My startup code:
package rfd;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
public class RfdWar
{
public static void main(String[] args) throws Exception
{
System.setProperty("org.eclipse.jetty.LEVEL", "DEBUG");
Server server = new Server(8080);
org.eclipse.jetty.webapp.Configuration.ClassList classlist = org.eclipse.jetty.webapp.Configuration.ClassList.setServerDefault(server);
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");
Resource jettyEnv = Resource.newSystemResource("jetty-env.xml");
XmlConfiguration conf = new XmlConfiguration(jettyEnv.getInputStream());
Object obj = conf.configure();
WebAppContext context = (WebAppContext)obj;
context.setWar("/tmp/thewar.war");
context.setContextPath("/");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();
}
}
My command line:
export JETTYHOME=<my_jetty_home>
JHL=$JETTYHOME/lib
export CLASSPATH=.:$JHL/jetty-server-9.2.10.v20150310.jar:$JHL/jetty-util-9.2.10.v20150310.jar:$JHL/jetty-http-9.2.10.v20150310.jar:$JHL/servlet-api-3.1.jar:$JHL/jetty-io-9.2.10.v20150310.jar:$JHL/jetty-webapp-9.2.10.v20150310.jar:$JHL/jetty-servlet-9.2.10.v20150310.jar:$JHL/jetty-security-9.2.10.v20150310.jar:$JHL/jetty-xml-9.2.10.v20150310.jar:$JHL/jetty-plus-9.2.10.v20150310.jar:$JHL/jetty-jndi-9.2.10.v20150310.jar:$JHL/jsp/javax.servlet.jsp-2.3.2.jar:$JHL/jsp/javax.servlet.jsp-api-2.3.1.jar
java rfd.RfdWar
The server does launch correctly and definitely reads web.xml packaged in the war. But when I try accessing the URL I'm getting an error that my class, that's packaged with the war, is missing.
Is there anything else I need to do to tell jetty to honor the classes packaged in the war?
This command ...
context.setParentLoaderPriority(true);
Basically says that when the webapp is attempting to load a class, the server classpath is checked first, then the webapp's classpath.
So if you happen to have the same classes in both places, the server version will be used, ignoring the one on the webapp.
Set this to false to get honest servlet spec behavior, with all of the WebApp classloader isolation.
Also, this is wrong, in many different ways.
Resource jettyEnv = Resource.newSystemResource("jetty-env.xml");
XmlConfiguration conf = new XmlConfiguration(jettyEnv.getInputStream());
Object obj = conf.configure();
WebAppContext context = (WebAppContext)obj;
The proper way to get jetty-env.xml to be loaded is to use the establish the WebApp and ClassList Configuration that performs this function from within the appropriate classloader and thread scope.
See documentation at https://www.eclipse.org/jetty/documentation/current/jndi-embedded.html
And prior answer at Can't get jetty to read jetty-env.xml

How to access EJB services from a grails standalone client

I've been having problems to access to my EJB services from a standalone client i've developed on grails 2.0.3. The EJB services are deployed on a glassfish server (Java). I tested this code on a netbeans tester class to access the EJBs:
Properties p = new Properties();
p.put("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
p.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
p.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
p.setProperty("org.omg.CORBA.ORBInitialHost", INTEGRATION_IP);
p.setProperty("org.omg.CORBA.ORBInitialPort", CORBA_PORT);
ctx = new InitialContext(p);
try {
this.admAuth = (AdmAuthenticationRemote) this.ctx.lookup(Tester.AUTHENTICATION_SERVICE_JNDI);
}catch(Exception e){
...
}
This Tester.AUTHENTICATION_SERVICE_JNDI is a variable tha contains the path to the deployed service, in this case something like "java:global/..." that represents the address to the service that is being requested. This way of accessing the services works perfectly from the tester, but when i try to do the same from grails doesn't works. I am able to create the context the same way, but when i invoke the ctx.lookup() call i get an exception:
Message: Lookup failed for 'java:global/...' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory,
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
Cause: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory,
java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
[Root exception is java.lang.RuntimeException: Orb initialization erorr]
The main exception is a naming exception, which means that it failed in the ctx.lookup(), but the cause is the orb initialization exception, which has another exception stack:
java.lang.RuntimeException: Orb initialization erorr
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
Caused by: java.lang.IllegalArgumentException: Can not set long field com.sun.corba.ee.impl.orb.ORBDataParserImpl.waitForResponseTimeout to java.lang.Integer
I'm really lost here. I've been having a lot of problems to get this going on grails, I had to get all glassfish jars (libs and modules) so it could make the InitialContext() call, but now i'm not sure if this is still a jar problem or a configuration problem or what it is.
I know that IllegalArgumentException occurs when u try to assign incompatible types in java, but i'm not setting anything like that, so i assume its an internal method initialization.
So the question is why is this exception coming up??
Is there another way to invoke my services from grails that works better??
The error is that you're trying to run your web application using the tomcat plugin in grails (using the command grails run-app). The problem is that when you try to create the InitialContext (com.sun.enterprise.naming.SerialInitContextFactory) groovy gives you an error casting some types if you're using the client libraries for GF 3.1. (I know that this is the problem, but I really don't know the reason for this. Because in theory this should work)
If you generate the .war file and you deploy in an AppServer, you can connect to your EJBs without problems. And if you deploy it on another GF server you don't have to import any of the client jars.
This will work perfect on production, the only problem is that you must compile and deploy your app on the GF server with every little change, and this is a bit annoying in development.
If you want to work outside of GF and using the command "grails run-app", you must modify two of the .jar GF 3.1 on your remote server, where you have the grails application:
1- The jar file $GLASSFISH_HOME/modules/glassfish-corba-omgapi.jar
You should search in the web the class com.sun.corba.ee.spi.orb.ParserImplBase, and modify this part
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
for this
if (name.equalsIgnoreCase("waitForResponseTimeout")) {
Object newValue = new Long(1800000);
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, newValue);
} else {
Field field = getAnyField(name);
field.setAccessible(true);
field.set(ParserImplBase.this, value);
}
this should resolve the java.lang.IllegalArgumentException
2- The jar file $GLASSFISH_HOME/modules/glassfish-corba-orb.jar
you must delete the javax.rmi.CORBA.PortableRemoteObjectClass class of this library, because this class have conflicts with one used by the grails plugin
PS:
If you do not want to have the GF client jars in your grails application, you can add to the classpath of your client machine the following libraries
$GLASSFISH_HOME/modules/ejb-container.jar
$GLASSFISH_HOME/modules/ejb.security.jar
$GLASSFISH_HOME/modules/management-api.jar
If you use the grails console with the grails run-app command, must modify the configuration file $GRAILS_HOME/conf/groovy-starter.conf whit this
load $GLASSFISH_HOME/modules/ejb-container.jar
load $GLASSFISH_HOME/modules/ejb.security.jar
load $GLASSFISH_HOME/modules/management-api.jar

Creating webservice and client with JBossWS using Complex objects as arguments and return types

I am developing a WebService and Client for it using JBoss 5.1.0GA. The JBossWs stack was already preinstalled with the binary that I downloaded and as I understand it is JBossWs 3.1.2GA
I have developed a web service using this setup and have also created a client successfully. This is what I have.
A pojo web service deployed as a war file.
#WebService
public class Service{
#WebMethod
public CompleObj getConfiguration() {
CompleObj oConf = new CompleObj ();
for (int i = 0; i < 10; i++) {
NestObj oInst = new BOpRepoInstance("Val1", "Val2", "Val3", "Val4");
oConf.addRepoInstance(oInst);
}
return oConf;
}
}
Here,
CompleObj => is a Complex Object that has a list of type NestObj. Its
getter/setters, toString and some other methods.
NextObj => has 4 variables of Type String. Its getter/setters,
toString, hashCode, equals and some other methods.
Got this web service deployed successfully.
Later created a client using the eclipse wizard for generating Web Service Client using WSDL document. It also created a sample client file which would call the webservice and fetch the return value. This also worked like a charm.
Now my problem is, when eclipse generated stubs for clients it created classes for CompleObj and NestObj. These classes only has the variables and its getters/setters (this make sense as these are being generated from WSDL doc). Thus i loose a lot of other methods that includes toString, hasCode, equals etc, which I want to use at the Client side as well.
Now how can I make use of the actual class files defined in the WebService project directly and avoid the client to use the generated ones. I can provide the class files as .jar binary for the Client project, I cant really get how to achieve this.
Another question is, the web service location is embedded in the stubs directly, what can i do to have the webservice location passed as part of the argument to the invocation code?
The classes which are generated in the client side are just place
holders it is not deserilized version of your own classes,When you
invoke the service it is used to carry your object to server then
the JBOOSWS will do the JAXB mapping to the actual classes. So you
can not make the your own classes to be used in the client side
though they are look same.
URL will be fixed in the stub code, since in eclipse while generating WS client the first
thing you must provide is, the WSDL URL,then eclipse will generate the
client code accordingly,so generated code is specific to the WSDL
you provided. If you want to pass the WSDL dynamically,then you
need to have your own code to generate the client stubs by passed
WSDL URL using any WSDLtoJAVA or any other utility.

Missing configuration resources in StrutsTestCase 2.1.4

I'm trying to use StrutsTestCase 2.1.4 to do unit testing on my Struts application. But when I tried to run the test, a "missing configuration resources for path /WEB-INF/web.xml" error happens.
I looked it up in the FAQ of StrutsTestCase, and followed the instruction to add my application path to the classpath. However, it didn't work.
Then I use the setConfigFile() method to specify the path of web.xml and struts-config.xml. As you see, it didn't work, either.
Here's the setUp() method override in my test class:
public void setUp() throws Exception {
super.setUp();
File web = new File("E:/JavaPros/stolon/STOLONCAS/web/");
this.setContextDirectory(web);
this.setConfigFile("E:/JavaPros/stolon/STOLONCAS/web/WEB-INF/web.xml");
this.setConfigFile("E:/JavaPros/stolon/STOLONCAS/web/WEB-INF/struts-config.xml");
}
One thing different by using this method is the error msg became "Missing configuration resource for path E:/JavaPros/stolon/STOLONCAS/build/web/WEB-INF/struts-config.xml". This makes me very confused for I'm absolutely sure that there is the struts-config.xml in that path.