OSGi Spring MVC Bundle Nightmare - java.lang.ClassNotFoundException: org.springframework.context.config.ContextNamespaceHandler not found from bundle - spring-mvc

I can not get my Spring MVC application to run as an OSGi bundle. This one has completely stumped me.
I'm trying to run a Spring 3 MVC bundle, but when starting up it can not find the namespace handlers required to use Spring. I've included the necessary import-packages, for org.springframework.context. I've checked that the org.springframework.context.config.ContextNamespaceHandler is installed on the Virgo server. There are no errors on starting the bundle in the server - so I'm pretty sure dependencies must be fulfilled.
Here's the exception I get when I try to make a request to the MVC dispatcher servlet;-
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]; nested exception is org.springframework.beans.FatalBeanException: NamespaceHandler class [org.springframework.context.config.ContextNamespaceHandler] for namespace [http://www.springframework.org/schema/context] not found; nested exception is java.lang.ClassNotFoundException: org.springframework.context.config.ContextNamespaceHandler not found from bundle [com.osgi-test.spring-mvc-bundle]
org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:412)
org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:170)
org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:140)
org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397)
org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$301(AbstractDelegatedExecutionApplicationContext.java:60)
org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$1.run(AbstractDelegatedExecutionApplicationContext.java:168)
org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.normalRefresh(AbstractDelegatedExecutionApplicationContext.java:164)
org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$NoDependenciesWaitRefreshExecutor.refresh(AbstractDelegatedExecutionApplicationContext.java:78)
org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:157)
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:442)
org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:458)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:339)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:306)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:127)
javax.servlet.GenericServlet.init(GenericServlet.java:244)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
org.eclipse.virgo.web.tomcat.support.ApplicationNameTrackingValve.invoke(ApplicationNameTrackingValve.java:33)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
java.lang.Thread.run(Thread.java:722)
The Manifest file in the bundle looks like this;-
Manifest-Version: 1.0
Export-Package: com.osgi-test.external;version="0.0.1.SNAPSHOT"
Bundle-ClassPath: .,WEB-INF/classes
Built-By: seth
Tool: Bnd-1.50.0
Bundle-Name: spring-mvc-bundle
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.7.0_06
Bundle-Version: 0.0.1.SNAPSHOT
Bnd-LastModified: 1347110247719
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.osgi-test.spring-mvc-bundle
Import-Package: com.osgi-test.external,javax.servlet.http;version="
[2.4,3)",org.eclipse.virgo.web.dm;version="[3.0,4)",org.springfram
ework.context;version="[3.0,4)",org.springframework.stereotype;ver
sion="[3.0,4)",org.springframework.validation;version="[3.0,4)",or
g.springframework.web;version="[3.0,4)",org.springframework.web.bi
nd.annotation;version="[3.0,4) ",org.springframework.web.servlet;v
ersion="[3.0,4)"
Archiver-Version: Plexus Archiver
I read an article that suggested making use of the
org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext
(http://www.eclipse.org/forums/index.php/m/635463/)
might help - however made no difference for me.
I have also tried removing the ContextLoaderListener in the web.xml - but again that didn't help.
At this point, I'm lost for ideas. Any help, massively appreciated.

http://thomaskratz.blogspot.in/2012/03/osgi-spring-dispatcherservlet.html
Please check this site, I think spring has issues with registering dispatcher servlet directly. But if you use the workaround mentioned in the above blog, it should work.
I am actually adding the code snippet which I tried here for reference:
Add the following to Activator of the plugin:
Activator.context = bundleContext;
ServiceReference ref = context.getServiceReference(HttpService.class.getName());
HttpService service = (HttpService) context.getService(ref);
DispatcherServlet servlet = new DispatcherServlet();
Dictionary<String, String> initparam = new Hashtable<String, String>();
initparam.put("contextConfigLocation", "/WebContent/WEB-INF/spring-servlet.xml");
initparam.put("contextClass", "spring3osgi.BAC");
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
// this is to register the controller
service.registerServlet("/Spring3OSGi", servlet, initparam, null);
// provide alias to the WebContent folder
service.registerResources("/Spring3OSGiWebContent", "/WebContent", service.createDefaultHttpContext());
Create a class BAC
import org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext;
public class BAC extends OsgiBundleXmlWebApplicationContext {
public BAC() {
super();
setBundleContext(Activator.getContext());
}
}

I don't know much about Spring MVC, but for Spring I know there is SpringDM specially for OSGi environments. Maybe you could have a look to http://static.springsource.org/osgi/docs/1.2.1/reference/html/web.html#web:spring-mvc. Hopefully it will help you a little bit.

Related

How do I add Thymeleaf SpringSecurityDialect to spring boot

In the configuration of my template engine I would like to add SpringSecurityDialect() like:
#Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new SpringSecurityDialect());
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
However eclipse is telling me:
The type org.thymeleaf.dialect.IExpressionEnhancingDialect cannot be resolved. It is indirectly referenced from required .class files
What does this mean and how can I fix it?
In pom.xml I have:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
As #Lachezar already answered, you have to add those missing dependencies. But the specified version with ext['thymeleaf.version'] = '3.0.0.RELEASE should be the same as in the compile dependencies so you better use ext['thymeleaf.version'] = '3.0.1.RELEASE'.
Furthermore, please note that it is enough to just specify a bean for the security dialect without providing a bean for the template engine. With Thymeleaf on the classpath, it will automatically recognize that the bean is an instance of IDialect and adds it directly to the dialects:
#Bean
public SpringSecurityDialect springSecurityDialect() {
return new SpringSecurityDialect();
}
It means that org.thymeleaf.extras:thymeleaf-extras-springsecurity4 has a dependency to org.thymeleaf:thymeleaf as you can see in the link to the repo above. Apparently you haven't provided this dependency. The class IExpressionEnhancingDialect is there. You can resolve that by adding the dependency to your project.
Since this may get a bit complicated... I'm also playing around with Spring Boot, spring security and the security dialect for thymeleaf (plus spring data with h2). Here are my gradle dependencies for reference, they may help you somehow:
ext['thymeleaf.version'] = '3.0.1.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.0.0'
dependencies {
compile("org.springframework.boot:spring-boot-devtools")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.1.RELEASE")
compile("com.h2database:h2")
}
Note that I want to use thymeleaf 3 instead of 2, that is why there are some extra unpleasant tweaks in my configuration.
EDIT: The version of thymeleaf-extras-springsecurity4 should be the same as thymeleaf.version as suggested in the other answer.

Export package in OSGi Bundle

I have an OSGi Bundle and a servlet. Now I want to access the bundle from the servlet. For that purpose I use the following in the servlet:
#Resource
BundleContext context
...
ServiceReference ref = context.getServiceReference("package.MyOSGiServiceInterface");
MyOSGiServiceInterface service = context.getService(ref);
The Problem is that my servlet doesn't know MyOSGiServiceInterface 'cause that is defined in the OSGiBundle. In Eclipse I added a reference to the bundle Project in my Build Path. But at runtime it obviously can't find it.
To solve that Problem I played around with
(in bundle manifest)
Export-Package: package-of-osgi-service-interface
(in servlet manifest)
Import-Package: package-of-osgi-service-Interface
Dependencies: ...,deployment.MyBundle
But I couldn't solve it.
Whats the missing step? How can I tell JBoss to add the package containing MyOSGiServiceInterface in OSGiBundle to the class path?
Thanks for answers!
(JBoss AS 7.1.1)
--> error message <--
Eventually I solved it. I had to put the right combination of settings together to reach my goal:
Deploy the bundle per: File - Export - "Deployable plug-ins and fragments" into folder: "jboss/standalone/deployments"
Bundle-Manifest:
Bundle-SymbolicName: TestBundle
Bundle-Version: 1.0.0
Export-Package: "package-which-includes-my-service"
Servlet-Manifest:
Dependencies: org.osgi.core,org.jboss.osgi.framework,deployment.TestBundle:1.0.0
Import-Package: "package-which-includes-my-service"

Servlet class is not a javax.servlet.Servlet

I am developing a GWT application, but I got the following Exception when I deploy it into a Equinox-jetty server:
404 Servlet class com.cartif.gui.autentication.server.AppServiceImpl is not a javax.servlet.Servlet <html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Error 404 Servlet class com.cartif.gui.autentication.server.AppServiceImpl is not a javax.servlet.Servlet</title>
</head>
<body><h2>HTTP ERROR 404</h2>
<p>Problem accessing /baasGUIAutentication/baasgui/autentication. Reason:
<pre>
Servlet class com.cartif.gui.autentication.server.AppServiceImpl is not a javax.servlet.Servlet</pre></p><h3>Caused by:</h3><pre>javax.servlet.UnavailableException: Servlet class com.cartif.gui.autentication.server.AppServiceImpl is not a javax.servlet.Servlet
at org.mortbay.jetty.servlet.ServletHolder.checkServletType(ServletHolder.java:362)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:243)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.springframework.osgi.web.deployer.jetty.JettyWarDeployer.startWebAppContext(JettyWarDeployer.java:210)
at org.springframework.osgi.web.deployer.jetty.JettyWarDeployer.startDeployment(JettyWarDeployer.java:122)
at org.springframework.osgi.web.deployer.support.AbstractWarDeployer.deploy(AbstractWarDeployer.java:93)
at org.springframework.osgi.web.extender.internal.activator.WarLoaderListener$DeploymentManager$DeployTask.doRun(WarLoaderListener.java:257)
at org.springframework.osgi.web.extender.internal.activator.WarLoaderListener$DeploymentManager$BaseTask.run(WarLoaderListener.java:215)
at org.springframework.scheduling.timer.DelegatingTimerTask.run(DelegatingTimerTask.java:66)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
</pre>
<hr /><i><small>Powered by Jetty://</small></i><br/>
The code header for the AppServiceImpl class is:
public class AppServiceImpl extends RemoteServiceServlet implements AppService
And AppService:
#RemoteServiceRelativePath("autentication")
public interface AppService extends RemoteService {
User getUser(String user, String pass) throws Exception;
}
Moreover, the web.xml declares the servlet as follows:
<servlet>
<servlet-name>baasguiServlet</servlet-name>
<servlet-class>com.cartif.gui.autentication.server.AppServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>baasguiServlet</servlet-name>
<url-pattern>/baasgui/autentication</url-pattern>
</servlet-mapping>
And baasgui is the folder where the GWT Java code is compiled. I have also checked the javax.servlet class and it is used only once.
Could anyone help me??
Thank you very much in advance!!
Jose
This typically happens if you embed the javax.servlet package into your bundle. Then jetty sees the normal javax.servlet deployed as a bundle while your application sees only the embedded class. So the interfaces are considered to be different.
The best solution is to not embed external stuff into your bundle. If you can not avoid it then export and import the javax.servlet package. So the framework can wire jetty and you bundle to the same classloader providing the package.
Start equinox with console
If it is equinox 3.7.x, -Dosgi.console=6666
If it is equinox 3.8 or newer: -Dosgi.console.enable.builtin=true -Dosgi.console=6666
You will be able to telnet to port 6666
Enter the command in telnet session: packages javax.servlet
In the result list, you will see that the package is available in your OSGi container multiple times. Jersey wires to one of them while your wab wires to the other one. Try to achieve having the package only ones in the container.
I got the solution. In the GWT libraries bundle I had to add the following lines:
Bundle-SymbolicName: gwtlibraries; singleton:=true
Require-Bundle: javax.servlet
Instead of importing packages, the tag Require-Bundle and the part of singleton bundle. Also in the GUI manifest I had to add the next line:
Bundle-SymbolicName: GUI; singleton:=true
Require-Bundle: gwtlibraries //apart from importing the specific libraries
Eclipse-RegisterBuddy: com.cartif.gwt
Eclipse-BuddyPolicy: registered
This was not happening with the previous versions of the GWT libraries I had deployed, but the bundle structure was different because now I am using the unzipped libraries and in previous ones the zipped jar files.
Thank you for your collaboration and help!!!!
Here is a rather mundane reason why I got this exception. I adapted my new servlet from an old servlet. Right above the class definition in the .java file, there is a line of the kind: #WebServlet(name="OldServlet",urlPatterns={"/OldServlet"}). Although I properly renamed my class from OldServlet to NewServlet throughout (in the java and web.xml files), I forgot to change the name in the above line. After I changed the above line to #WebServlet(name="NewServlet",urlPatterns={"/NewServlet"}), I stopped getting this exception. Hope this helps.

WELD-001408 Unsatisfied dependencies inject point

I have a working Dynamic Web Project (JAX-RS) in eclipse which fetches records from database and return data in json format.
Now, i am trying to split this project into two.
1. CompDB //Project stores database handlers classes
src
database
ComponentContext.java
ComponentViewable.java //Interface
database.uat
ComponentUATView.java //Implements ComponentViewable
META-INF
persistance.xml
WebContent
WEB-INF
beans.xml
web.xml
Created a jar file and copied onto WEB-INF/lib of project 2 as below
2. CompRS //Project stores JAX-RS client classes
src
compreport
ComponentData.java
META-INF
persistance.xml
WebContent
WEB-INF
lib
CompDB.jar
beans.xml
web.xml
When I run CompRS on glssfish 3.1, getting below error
INFO: WEB0671: Loading application [CompRS] at [/CompRS] SEVERE: Exception while loading the app
INFO: file:/C:/Program Files/glassfish-3.1.2.2/glassfish/domains/domain1/eclipseApps/CompRS/WEB- INF/lib/CompDB.jar_ci logout successful
SEVERE: Exception while loading the app : WELD-001408 Unsatisfied dependencies for type
[ComponentViewable] with qualifiers [#ComponentContext] at injection point [[field] #Inject #ComponentContext compreport.ComponentData.componentdata]
Here is the code
ComponentData.java
#Path("component")
#RequestScoped
public class ComponentData {
#Inject #ComponentContext ComponentViewable componentdata;
#GET
#Path("latest")
#Produces("application/json")
....
}
ComponentContext.java
#Target({TYPE,METHOD,PARAMETER,FIELD})
#Retention(RUNTIME) #Documented #Qualifier
public #interface ComponentContext{}
I am very new to create multiple jars and integrate them. If this is not the correct way to do, please guide me to achieve the same.
It looks like CompDB is now a jar that you're referencing from the other web app. The beans.xml files in a jar must be in META-INF.

seam solder (former weld-extensions project) is not initialized

I want to use logger in my java web application.
I'm using JBossAS 6.0.0.final, cdi (weld), jsf ... etc. Seam solder proposes to use an abstract logger is not tying to a concrete implementation (slf4j, log4j, etc) using jboss-logging api.
In order to get this logger in your code will need to write
# Inject
org.jboss.logging.Logger log
seam-solder.jar has the producer for this logger.
package org.jboss.seam.solder.log;
...
class LoggerProducers
{
# Produces
org.jboss.logging.Logger produceLog (InjectionPoint injectionPoint) {}
}
When I deploying my application, I get an error
15:51:18,300 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to Start: name=vfs:///C:/Java/jboss-6.0.0.Final/server/default/deploy/kamis-web-client.5.0.0-SNAPSHOT.ear_WeldBootstrapBean state=Create: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Logger] with qualifiers [#Default] at injection point [[field] #Inject private ru.kamis.suite.webclient.web.breadcrumbs.BreadcrumbsManager.log]
This is due to the seam-solder.jar has not META-INF/beans.xml file, and it is necessary for cdi container.
If to add beans.xml file in seam-solder.jar manually, then the application works WELL.
How to do without hacks?
To build my application I use maven, so my solution is not comfortable and NOT fine.
PS: Former weld-extensions project contained META-INF/beans.xml file in jar.
with seam-solder-3.0.0.Beta1 there should be no need to modify the jar

Resources