Spring MVC on WebSphere Liberty, 404s on all Spring URLs - eclipse

Eclipse Oxygen with WebSphere Development Tools (WDT), Spring MVC 4.3.14, WebSphere Liberty Core 18.0.0.1 on Java 8. Liberty Features enabled (deliberately not latest) are:
<featureManager>
<feature>adminCenter-1.0</feature>
<feature>localConnector-1.0</feature>
<feature>jaxrs-1.1</feature>
<feature>concurrent-1.0</feature>
<feature>webProfile-6.0</feature>
<feature>jaxb-2.2</feature>
</featureManager>
JSPs on the context root are working fine, so that's correct. Also, ibm-web-ext.xml has <context-root uri="/webapp/gatewaymvm/" />
The Spring startup logging indicates that my #Controller classes are binding to the paths I expect:
10:31:24,102 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:Looking for request mappings in application context: WebApplicationContext for namespace 'Spring MVC Dispatcher-servlet': startup date [Thu Apr 05 10:31:22 CDT 2018]; parent: Root WebApplicationContext
....
10:31:24,125 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:1 request handler methods found on class mypackage.QueryTransactionController: {public mypackage.QueryTransResponse mypackage.QueryTransactionController.processRequest(mypackage.QueryTransRequest,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException={[/QueryTransaction],methods=[POST],consumes=[application/json || application/xml],produces=[application/json || application/xml]}}
10:31:24,125 INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:Mapped "{[/QueryTransaction],methods=[POST],consumes=[application/json || application/xml],produces=[application/json || application/xml]}" onto public mypackage.QueryTransResponse mypackage.QueryTransactionController.processRequest(mypackage.QueryTransRequest,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException
...
10:31:24,130 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:1 request handler methods found on class mypackage.TestPostJSONDocumentController: {public java.lang.String mypackage.TestPostDocumentController.execute(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException={[/testPostJSONDoc],methods=[POST]}}
10:31:24,130 INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:Mapped "{[/testPostJSONDoc],methods=[POST]}" onto public java.lang.String mypackage.TestPostDocumentController.execute(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException
Yet, when I hit any of those URLs, they produce 404 responses and log entries like the following:
10:32:40,067 DEBUG org.springframework.web.servlet.DispatcherServlet:DispatcherServlet with name 'Spring MVC Dispatcher' processing POST request for [/webapp/gatewaymvm/testPostJSONDoc]
10:32:40,067 DEBUG org.springframework.webflow.mvc.servlet.FlowHandlerMapping:No flow mapping found for request with URI '/webapp/gatewaymvm/testPostJSONDoc'
10:32:40,068 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:Looking up handler method for path testPostJSONDoc
10:32:40,075 DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping:Did not find handler method for [testPostJSONDoc]
10:32:40,076 WARN org.springframework.web.servlet.PageNotFound:No mapping found for HTTP request with URI [/webapp/gatewaymvm/testPostJSONDoc] in DispatcherServlet with name 'Spring MVC Dispatcher'
This same application, when deployed to "Traditional" WAS, works as expected. I imagine there's something obvious I'm missing about Liberty, Liberty under Eclipse, or Spring MVC under Liberty.

At some point during my testing, where I had code that constructed a URL from the current request, I had seen /webapp/gatewaymvm//resource, with two slashes together.
So I tried removing the trailing slash from the places where I had a context root of /webapp/gatewaymvm/, and that resolved the issue. Either from server.xml if I have the WAR installed there directly, or from application.xml if I have the WAR installed in an EAR/Enterprise project.
Interesting that the JSPs worked with the trailing slash there, but the Spring paths did not.

Related

How to share the session in multiple WAR in EAR file in JBOSS-7.3.6

How to share the session in multiple WAR in EAR file in JBOSS-7.3.6 ?
we have following entry in jboss-all.xml JBoss 7.2 version (before migration)
<jboss xmlns="urn:jboss:1.0">
<shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
<max-active-sessions>10</max-active-sessions>
<session-config>
<session-timeout>0</session-timeout>
<cookie-config>
<name>JSESSIONID</name>
<domain>domainName</domain>
<path>/cookiePath</path>
<comment>cookie comment</comment>
<http-only>true</http-only>
<secure>true</secure>
<max-age>-1</max-age>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
<replication-config>
<cache-name>web</cache-name>
<replication-granularity>SESSION</replication-granularity>
</replication-config>
</shared-session-config>
</jboss>
But now I'm putting the same xml.. or below xml snippet but could not work in JBOSS-7.3.6
<shared-session-config xmlns="urn:jboss:shared-session-config:2.0">
<distributable/>
<max-active-sessions>10</max-active-sessions>
-- rest copy from above
getting the following exception
21:50:31,221 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to URL: java.lang.IllegalStateException: WFLYCLWEBUT0001: Session idKL5QLs4873uTTnzT6JFg03_avxMEa8Q1-B4Jy4 is invalid
at org.wildfly.clustering.web.undertow.session.DistributableSession.validate(DistributableSession.java:265)
at org.wildfly.clustering.web.undertow.session.DistributableSession.validate(DistributableSession.java:257)
Can anyone suggest how to achieve ?
Thanks in advance !
First of all you have to know that sharing sessions between web applications would violate the JavaEE Servlet specification! That means your applications may not be portable! However you can check the coresponding documentation for more info: Development Guide / Configuring Session Sharing Between Subdeployments In Enterprise Archives

started geode spring boot and save to remote region but failed to start bean gemfireClusterSchemaObjectInitializer

With a simple client app, make an object and object repository, connect to a Geode cluster, then run a #Bean ApplicationRunner to put some data to a remote region.
#ClientCacheApplication(name = "Web", locators = #Locator, logLevel = "debug", subscriptionEnabled = true)
#EnableClusterDefinedRegions
#EnableClusterConfiguration(useHttp = true)
#EnablePdx
public class MyCache {
private static final Logger log = LoggerFactory.getLogger(MyCache.class);
#Bean
ApplicationRunner StartedUp(MyRepository myRepo){
log.info("In StartedUp");
return args -> {
String guid = UUID.randomUUID().toString().substring(0, 8).toUpperCase();
MyObject msg = new MyObject(guid, "Started");
myRepo.save(msg);
log.info("Out StartedUp");
};
}
The "save" put fails with
org.springframework.context.ApplicationContextException: Failed to start bean 'gemfireClusterSchemaObjectInitializer'; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://localhost:7070/gemfire/v1/regions": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
Problem creating region and persist region to disk Geode Gemfire Spring Boot helped. The problem is the #EnableClusterConfiguration(useHttp = true)
This annotation makes the remote cluster appear to be a localhost. If I remove it altogether then the put works.
If remove just the useHttp = true there is another error:
org.springframework.context.ApplicationContextException: Failed to start bean 'gemfireClusterSchemaObjectInitializer'; nested exception is org.apache.geode.cache.client.ServerOperationException: remote server on #.#.#.#(Web:9408:loner)### The function is not registered for function id CreateRegionFunction
In a nutshell, the SDG #EnableClusterConfiguration annotation (details available here) enables configuration metadata defined and declared on the client (i.e. Spring [Boot] Data, GemFire/Geode application) to be pushed from the client-side to the cluster (of GemFire/Geode servers).
I say "enable" because it depends on the client-side configuration metadata (i.e. Spring bean definitions you have explicitly or implicitly defined/declared). Explicit configuration is configuration you defined with a bean definition (in XML, or JavaConfig with #Bean, etc). Implicit configuration is auto-configuration or using SDG annotations like #EnableEntityDefinedRegions or #EnableCachingDefinedRegions, etc.
By default, the #EnableClusterConfiguration annotation assumes the cluster of GemFire or Geode servers were configured and bootstrapped with Spring, and specifically using the SDG Annotation configuration model. When the GemFire or Geode servers are configured and bootstrapped with Spring, then SDG goes on to register some provided, canned GemFire Functions that the #EnableClusterConfiguration annotation calls (by default and...) as a fallback.
NOTE: See the appendix in the SBDG reference documentation on configuring and bootstrapping a GemFire or Geode server, or even a cluster of servers, with Spring. This certainly simplifies local development and debugging as opposed to using Gfsh. You can do all sorts of interesting combinations: Gfsh Locator with Spring servers, Spring [embedded|standalone] Locator with both Gfsh and Spring servers, etc.
Most of the time, users are using Spring on the client and Gfsh to (partially) configure and bootstrap their cluster (of servers). When this is the case, then Spring is generally not on the servers' classpath and the "provided, canned" Functions I referred to above are not present and automatically registered. In which case, you must rely on GemFire/Geodes internal, Management REST API (something I know a thing or 2 about, ;-) to send the configuration metadata from the client to the server/cluster. This is why the useHttp attribute on the #EnableClusterConfiguration annotation must be set to true.
This is why you saw the Exception...
org.springframework.context.ApplicationContextException: Failed to start bean 'gemfireClusterSchemaObjectInitializer';
nested exception is org.apache.geode.cache.client.ServerOperationException: remote server on #.#.#.#(Web:9408:loner)###
The function is not registered for function id CreateRegionFunction
The CreateRegionFunction is the canned Function provided by SDG out of the box, but only when Spring is used to both configure and bootstrap the servers in the cluster.
This generally works well for CI/CD environments, and especially our own test infrastructure since we typically do not have a full installations of either Apache Geode or Pivotal GemFire available to test with in those environments. For 1, those artifacts must be resolvable from and artifact repository like Maven Central. The Apache Geode (and especially) Pivotal GemFire distributions are not. The JARs are, but the full distro isn't. Anyway...
Hopefully, all of this makes sense up to this point.
I do have a recommendation if I may.
Given your application class definition begins with...
#ClientCacheApplication(name = "Web", locators = #Locator,
logLevel = "debug", subscriptionEnabled = true)
#EnableClusterDefinedRegions
#EnableClusterConfiguration(useHttp = true)
#EnablePdx
public class MyCache { ... }
I would highly recommend simply using Spring Boot for Apache Geode (and Pivotal GemFire), i.e. SBDG, in place of SDG directly.
Your application class could then be simplified to:
#SpringBootApplication
#EnableClusterAware
#EnableClusterDefinedRegions
public class MyCache { ... }
You can then externalize some of the hard coded configuration settings using the Spring Boot application.properties file:
spring.application.name=Web
spring.data.gemfire.cache.log-level=debug
spring.data.gemfire.pool.subscription-enabled=true
NOTE: #EnableClusterAware is a much more robust and capable extension of #EnableClusterConfiguration. See additional details here.
Here are a few resources to get you going:
Project Overview
Getting Started Sample Guide
Use Case Driven Guides/Samples
Useful resources in the Appendix TOC.
Detailed information on SBDG provided Auto-configuration.
Detailed information on Declarative Configuration.
Detailed information on Externalized Configuration.
In general, SBDG, which is based on SDG, SSDG and STDG, is the preferred/recommended starting point for all things Spring for Apache Geode and Pivotal GemFire (or now, Pivotal Cloud Cache).
Hope this helps.

Resteasy Bean Validation Not Working on Remote Server

I have a problem similar to the one described here.
I am using RESTEasy within a standalone Jetty application. When I start the application locally and call a service (e.g. localhost:16880/rest/user/login) bean validation works fine, i.e. I get validation errors like this:
[PARAMETER]
[UserService#login(arg0).appKey]
[app_key may not be null or empty]
[]
However, when I deploy my application to a remote host and call the same service (e.g. remotehost:16880/rest/user/login) bean validation is not invoked at all.
I am using the #ValidateRequest annotation for the service and #Valid annotation for the bean parameter.
My Resteasy version is 3.0.13.Final, though I have tried earlier versions as well. I have tried to write my custom validator, but that didn't work either.
I am puzzled why the validation works locally, but not on remote server. Any suggestions would be highly appreciated.
Since you are using Jetty as standalone server, you have to define RESTEasy validation providers where you define ServletContextHandler. Note that in standalone server there is no container to scan for #Provider classes and to activate them, so you must do it manually.
I expect that you create and start your server app something like:
//create a server listening at some port
Server server= new Server(port);
//add server handlers
HandlerList handlers= new HandlerList();
initHandlers(handlers);
server.setHandler(handlers);
//start the server
server.start();
In initHandlers you must have defined your RESTEasy support:
public void initHandlers(List<HandlerList> handlers) {
//define root context handler
ServletContextHandler servletContextHandler= new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
handlers.addHandler(servletContextHandler);
//define RESTEasy handler
ServletHolder restServlet= new ServletHolder(new HttpServlet30Dispatcher());
//since this is a standalone server, somewhere you have to define RESTful services and Singletons
restServlet.setInitParameter("javax.ws.rs.Application", "com.exampleapp.MyRestApplication");
restServlet.setInitParameter("resteasy.servlet.mapping.prefix", "rest");
servletContextHandler.addServlet(restServlet, "rest/*");
}
So what is left to do now is to add Validation provider as init parameter:
restServlet.setInitParameter("resteasy.providers", "org.jboss.resteasy.plugins.validation.ValidatorContextResolver,org.jboss.resteasy.api.validation.ResteasyViolationExceptionMapper");
On this link I tried to find the name of the validator providers: https://docs.jboss.org/resteasy/docs/3.0.4.Final/userguide/html/Validation.html
RESTEasy obtains a bean validation implemenation by looking in the available META-INF/services/javax.ws.rs.Providers files for an implementation of ContextResolver
So it does not say what, but says where. Now open the "resteasy-hibernatevalidator-provider-3...*.jar (from Eclipse -> Maven dependencies or manually unzip) and look into META-INF/services/javax.ws.rs.ext.Providers It says:
org.jboss.resteasy.plugins.validation.hibernate.ValidatorContextResolver
org.jboss.resteasy.api.validation.ResteasyViolationExceptionMapper
If you don't have this dependency, then add it to your pom file:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-hibernatevalidator-provider</artifactId>
<version>${resteasy.version}</version>
</dependency>
One more note: that at the same place where you described validation providers, you also add other providers, if you happen to need them (such as JacksonJaxbJson, etc).

Injecting EJB within JAX-RS resource in JBoss 5

Although there already are quite some StackOverflow questions, blog entries, etc. on the web, I still cannot figure out a solution to the problem stated below.
Similar to this question (Injecting EJB within JAX-RS resource on JBoss7) I'd like to inject a EJB instance into a JAX-RS class. I tried with JBoss 5, JBoss 7, and WildFly 8. I either get no injection at all (field is null), or the server does not deploy (as soon as I try to combine all sorts of annotations).
Adding #Stateless to the JAX-RS makes the application server know both classes as beans. However, no injection takes place.
Is there a way to inject EJBs into a REST application? What kind of information (in addition to that contained in the question linked to above) could I provide to help?
EDIT: I created a Github project showing code that works (with Glassfish 4.0) and does not work (with JBoss 5).
https://github.com/C-Otto/beantest
Commit 4bf2f3d23f49d106a435f068ed9b30701bbedc9d works using Glassfish
4.0.
Commit 50d137674e55e1ceb512fe0029b9555ff7c2ec21 uses Jersey 1.8, which does not work.
Commit 86004b7fb6263d66bda7dd302f2d2a714ff3b939
uses Jersey 2.6, which also does not work.
EDIT2:
Running the Code which I tried on JBoss 5 on Glassfish 4.0 gives:
Exception while loading the app : CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Ref<ContainerRequest>] with qualifiers [#Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] #Inject org.glassfish.jersey.server.internal.routing.UriRoutingContext(Ref<ContainerRequest>, ProcessingProviders)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:403)
EDIT3: The crucial information might be that I'd like a solution that works on JBoss 5
If you don't want to make your JAX-RS resource an EJB too (#Stateless) and then use #EJB or #Resource to inject it, you can always go with JNDI lookup (I tend to write a "ServiceLocator" class that gets a service via its class.
A nice resource to read about the topic:
https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project
A sample code:
try {
// 1. Retreive the Home Interface using a JNDI Lookup
// Retrieve the initial context for JNDI. // No properties needed when local
Context context = new InitialContext();
// Retrieve the home interface using a JNDI lookup using
// the java:comp/env bean environment variable // specified in web.xml
helloHome = (HelloLocalHome) context.lookup("java:comp/env/ejb/HelloBean");
//2. Narrow the returned object to be an HelloHome object. // Since the client is local, cast it to the correct object type.
//3. Create the local Hello bean instance, return the reference
hello = (HelloLocal)helloHome.create();
} catch(NamingException e) {
} catch(CreateException e) {
}
This is not "injecting" per-se, but you don't use "new" as-well, and you let the application server give you an instance which is managed.
I hope this was useful and I'm not telling you something you already know!
EDIT:
This is an excellent example: https://docs.jboss.org/author/display/AS72/EJB+invocations+from+a+remote+client+using+JNDI
EDIT 2:
As you stated in your comment, you'd like to inject it via annotations.
If the JNDI lookup is currently working for you without problems, and
If you're using Java EE 6+ (which I'm guessing you are), you can do the following:
#EJB(lookup = "jndi-lookup-string-here")
private RemoteInterface bean;

Glassfish 3.x start failed

i'm trying to run my java EE web application on Glassfish v3.x on Netbeans 7 but it wont work, and gives me the following error: Glassfish 3.x start failed.
i don't know what's the problem glassfish used to work fine before but then suddenly stoped working i unistalled netbeans and glassfish n install it again, but still the same problem.
here is the glassfish log:
Launching GlassFish on Felix platform
INFO: Registered org.glassfish.ha.store.adapter.cache.ShoalBackingStoreProxy for persistence-type = replicated in BackingStoreFactoryRegistry
INFO: Grizzly Framework 1.9.31 started in: 585ms - bound to [0.0.0.0:3700]
INFO: Grizzly Framework 1.9.31 started in: 580ms - bound to [0.0.0.0:8181]
INFO: Grizzly Framework 1.9.31 started in: 738ms - bound to [0.0.0.0:8080]
INFO: Grizzly Framework 1.9.31 started in: 584ms - bound to [0.0.0.0:7676]
INFO: Grizzly Framework 1.9.31 started in: 539ms - bound to [0.0.0.0:4848]
GRAVE: Exception while visiting com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class of size 84805
java.lang.ArrayIndexOutOfBoundsException: 48188
at org.objectweb.asm.ClassReader.readClass(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.glassfish.hk2.classmodel.reflect.Parser$5.on(Parser.java:362)
at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.handleEntry(ReadableArchiveScannerAdapter.java:171)
at com.sun.enterprise.v3.server.ReadableArchiveScannerAdapter.onSelectedEntries(ReadableArchiveScannerAdapter.java:133)
at org.glassfish.hk2.classmodel.reflect.Parser.doJob(Parser.java:346)
at org.glassfish.hk2.classmodel.reflect.Parser.access$300(Parser.java:70)
at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:305)
at org.glassfish.hk2.classmodel.reflect.Parser$3.call(Parser.java:294)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
INFO: SEC1002: Security Manager is OFF.
INFO: SEC1010: Entering Security Startup Service
INFO: SEC1143: Loading policy provider com.sun.enterprise.security.provider.PolicyWrapper.
INFO: SEC1115: Realm [admin-realm] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
INFO: SEC1115: Realm [file] of classtype [com.sun.enterprise.security.auth.realm.file.FileRealm] successfully created.
INFO: SEC1115: Realm [certificate] of classtype [com.sun.enterprise.security.auth.realm.certificate.CertificateRealm] successfully created.
INFO: SEC1011: Security Service(s) Started Successfully
INFO: WEB0169: Created HTTP listener [http-listener-1] on host/port [0.0.0.0:8080]
INFO: WEB0169: Created HTTP listener [http-listener-2] on host/port [0.0.0.0:8181]
INFO: WEB0169: Created HTTP listener [admin-listener] on host/port [0.0.0.0:4848]
INFO: WEB0171: Created virtual server [server]
INFO: WEB0171: Created virtual server [__asadmin]
INFO: WEB0172: Virtual server [server] loaded default web module []
INFO: Initialisation de Mojarra 2.1.0 (FCS 2.1.0-b11) pour le contexte '/mavenproject1'
INFO: Monitoring jndi:/server/mavenproject1/WEB-INF/faces-config.xml for modifications
INFO: PWC1412: WebModule[null] ServletContext.log():Initializing Spring root WebApplicationContext
Best Regards.
I know this was asked months ago but this question being one of the few sources i found in Google when encountering this problem, I think it'd good to share what bit i learnt:
I had the same exact problem and tried both things stated above. Still, my XML files didn't seem to be corrupted. In the end I found that the root of the problem was on the icu4j library which was, dont know why, among the dependencies in my project. Once I removed it, I was free of that error at last!
Should also be noted that Netbeans 7.0.1 (The IDE I'm using) also "uses" this library. I moved this library out of its original location just in case. NB continues to run without any problems so far.
Hope it helps someone else too!
I fixed mine in this way. It seemed that my XML file for the domain was corrupt ( I have no idea how) but what i did is as follows:
Remove your current server from the server node( right click and remove), then make a new server, except when it says to pick a domain, type in your own domain name (EX. myDomain) and then set up the server.
Wait for a few seconds, and bam, new XML file, not corrupt, and you should be able to run your server perfectly fine!
That's strange... How it does say "startup failed" if it loaded your app? Take a look at the last three lines of the log!
I had some problems like this, but all I needed is to right-click on the GF server node on "Services" tab and "refresh" it. Usually NB consider a slow GF startup as "failed".
Another answer which is possible now if using Java 8, but not at the time the OP asked, is that the server code contains lambdas. If you do have lambdas in your code, try to replace them with anonymous inner classes and your class(es) that were affected should now be good to go.