How can I configure the JAX-RS base path in TomEE+? - cxf

I have a WAR with some JAX-RS services, deployed into TomEE Plus. Given a service annotated with #Path("myservice"), TomEE+ publishes it to localhost:8080/mywebapp/myservice.
However, that also makes accessing a JSP at localhost:8080/mywebapp/index.jsp impossible - JAXRSInInterceptor complains that No root resource matching request path has been found, Relative Path: /index.jsp.
So I would like to configure a path prefix api to all services, which changes the myservice URL to localhost:8080/mywebapp/api/myservice. Doing so would be trivial if I had configured CXF on my own (with or without Spring), because I could simply change the URL pattern of the CXF Servlet - but I am relying on the default settings where I don't configure anything besides the annotations. So how do I do that in this case?
Note that I don't want to alter the #Path annotations to include the prefix, because that does not fix the issue with the JSP.

Create an extension of javax.ws.rs.core.Application and annotate it with #ApplicationPath where value would be api in your case:
#ApplicationPath("/api")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<Class<?>>();
// register root resource
classes.add(MyServiceResource.class);
return classes;
}
}
This way a Servlet 3 container would find your application and map your resource to /mywebapp/api/myservice while making your web resources (.jsp) available at /mywebapp.

TomEE trunk supports these configurations: cxf.jaxrs.staticSubresourceResolution & cxf.jaxrs.static-resources-list
but the #ApplicationPath is the more relevant solution IMO
Using -Dopenejb.webservice.old-deployment=true can help too in some cases

Related

How to use same CamelContext in multiple jar on the same war

I'm using the camel 2.16.2 and I need to use the one CamelContext across multiple jars as I need to have all the Camel Routers in to one CamelContext. So my war will have all those jars as maven artifacts.
Please let me know how do I handle above scenario?
Edit
Just to elaborate more on above question.
In my war myApp.war, I have initialized the CamelContext. There are three jars myApp1.jar, myApp2.jar and myApp3.jar. Each jar has it own routers defined separately.
How do I start the routers in each jar ?
Can I use the same CamelContext injected to each routers?
If I cannot handle through jars, is it possible to implement with multiple war (myApp1.war, myApp2.war and myApp3.war) and each war having different camelContext and communicate to those routers from the main war (myApp.war) ?
As other guys said, you can't use the same CamelContext across different Jars. Could you explain a little what you want to do?
IMHO what you want to do is use routes defined in different Jars. So for that you can define a Camel Context and add all the routes from different Jars. Of course your Camel-Context-JAR has to have access to all those jars.
<camel:camelContext id="camel5">
<camel:package>org.apache.camel.spring.example</camel:package>
</camel:camelContext>
Or class by class
<camelContext id="camel5" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="myBuilder" />
</camelContext>
<bean id="myBuilder" class="org.apache.camel.spring.example.test1.MyRouteBuilder"/>
Or if you are using CDI you can follow this great article https://dzone.com/articles/using-camel-routes-in-java-ee-components
Reference: http://camel.apache.org/spring.html
After doing some research found a way to implement this. Infact we can use the same CamelContext across different jars as all jars are in the same war (Web Container).
We can implement easily with Apache Camel 2.16.2 with camel CDI. If you're using wildfly to deploy your war then you may need to add the camel patch. Download the the wildfly 9.0.2 pach
Steps are Given Below.
In your war create a servlet or restService and Inject the camelContext.
#Inject
#ContextName("cdi-context")
private CamelContext camelctx;
Create a router in the jar with below annotation.
#Startup
#ApplicationScoped
public class MyJRouteBuilder extends RouteBuilder {
In Configure method add
#Override
public void configure() throws Exception {
from("direct:startTwo").routeId("MyJRouteBuilder")
.bean(new SomeBeanThree());
}
Create a BootStrap Class in your jar and add the Router
#Singleton
#Startup
public class BootStrap {
private CamelContext camelctx;
#PostConstruct
public void init() throws Exception {
camelctx.addRoutes(new MyJRouteBuilder());
}
Add your jar as a artifact in the war pom.xml. Once you deploy the war you can see MyJRouteBuilder is Registred in the cdi-context CamelContext. So now you can access your Router anywhere you want.
Hope this would useful anyone who has the same issue what I had.

AspectJ advice not being detected in Spring application

I had an existing WAR with the following Spring (4.0.6.RELEASE) configuration:
<beans>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
</beans>
To this application I added the following annotation interface (copied verbatim):
package org.example;
#Documented
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.METHOD })
public #interface Logged {}
the following Aspect class (copied verbatim as well):
package org.example;
#Aspect
#Component
public class LoggingAspect
{
#Before("#annotation(Logged)")
public void before()
{
System.out.println("LoggingAspect.before()");
}
}
and the following batch processing class (copied verbatim):
package org.example;
#Component
public class Batch
{
#Logged
#Scheduled(fixedDelay = 100)
public void execute()
{
System.out.println("Batch.execute()");
}
}
The Spring configuration was then changed to:
<beans>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:annotation-config/>
<context:component-scan base-package="org.example"/>
<task:annotation-driven executor="executor" scheduler="scheduler"/>
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="5"/>
</beans>
I was expecting to see the following messages on the console:
LoggingAspect.before()
Batch.execute()
However, I only see the second of these messages (that is, the aspect code is not being called).
I took out this code to a sample application and interestingly the two messages appear just fine in the sample app. I then compared every single file in the actual application with the sample and ensured that everything is exactly the same, including the class and file names. Yet, the aspect does not work in the actual application.
Upon turning on debug level logging in both applications, the sample application shows the following log message:
DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void org.example.LoggingAspect.before()
but the actual application does not have this log message. This seems to indicate that the sample app detects the aspect method but the actual app does not. Both use the same Spring and AspectJ versions (4.0.6.RELEASE and 1.8.1 respectively). There are no errors in either log.
Spring instantiates LoggingAspect in both cases (gleaned from the logs).
I have also checked various JAR dependencies for the two apps and everything is the same, except that the actual app uses Spring ORM, Hibernate and EHCACHE JARs which the sample app does not.
Any pointers on what else should be checked will be useful.
Despite debugging the application for months, upgrading and degrading various Spring and AspectJ versions, the problem could not be resolved. Funnily enough, a sample application created out of the affected classes did not show any problems.
I had to finally circumvent the problem by specifying the aspect in the Spring configuration. The line:
<aop:aspectj-autoproxy proxy-target-class="true"/>
had to be changed to:
<aop:aspectj-autoproxy proxy-target-class="true">
<aop:include name="loggingAspect"/>
</aop:aspectj-autoproxy>
In this case loggingAspect is the default bean name assigned by the Spring framework to the instance of the bean class LoggingAspect. If the bean name is set to a different value, that value must be used with <aop:include />.

Durandal, Breeze, and DotNetNuke

I am developing a SPA as a DotNetNuke module. Everything works well, but I can't find a way to make the module work with Breeze. The DNN version i am using is 7.04, which is I think the latest. DNN uses its own WebApi (written on top of WebApi) and the modules have no AppStart folder.
I added this part after some thought
In DNN you can add a route like so:
public class RouteMapper : IServiceRouteMapper
{
public void RegisterRoutes(IMapRoute mapRouteManager)
{
mapRouteManager.MapHttpRoute("MyModuleName", "default", "{controller}/{action}",
new[] { "MyModule.NameSpace" });
//Second route....
//third rout.....
}
}
Breeze on the other hand register the route on AppStart using the WebActivator.PreApplicationStartMethod.
It seems to me that all I need to do is to add a route to the code above and just refer to Breeze as another DNN Module like so
mapRouteManager.MapHttpRoute("BreezeApi,"Breeze", "api/{controller}/{action}...
But according to the comments on breeze's startup class, breeze route should be inserted at the front of ALL api route so I suspect it won't work. Does anybody have any idea?

Hosting nancy with asp.net on IIS 6 - failed - wrong configuration

I tried some stuff to host a little nancy test api under IIS 6:
https://github.com/NancyFx/Nancy/wiki/Hosting-nancy-with-asp.net
http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx
But it dont work. Here are my steps:
Create Empty Nancy Web Application
Add Reference with nuget - Nancy.Hosting.Aspnet Version 0.15.1
new Web.config is modifyed automatically
as described in the wiki
Add new class in solution root - HelloModule.cs
insert test code "HelloWorld"
Publish the web site local
on Windows 2003
with a virtual Directory in the IIS manager
Browsing the url 'localhost/nancyTest' brings an HTTP 403 ERROR.
A little ASP.NET WebApplication runs with the same configuration.
The nancyTest application does not have a start site like default.aspx. I want to get the request response from .../nancyTest/ coded as:
public class HelloModule : NancyModule
{
public HelloModule()
{
Get["/"] = parameters => "Hello World";
}
}
Perhaps the call .../nancyTest/ is not a GET Request? Are there other things to go in more detail?
I know not so many people user IIS6 nowadays, but there is the following solution, i wish it can help some people that still use this old one,
Config aspnet_isapi to handle a new ext files and like , .start
Set default page for this application is index.start
In nancy module add the redirect method, like the follwing:
Get["index.start"] = _ => {
return Response.AsRedirect("~/", Nancy.Responses.RedirectResponse.RedirectType.Permanent);
};
wish it helps

Weld CDI on Google App Engine: Injection in servlet not happening

This is my first time working with GAE and I'm trying to get CDI working. Long story short: The #Inject field in my servlet is not getting injected (it's always null).
I'm working in Eclipse and debug the application on the local test server included in the GAE SDK (which is started by Eclipse as well). When I access the servlet on localhost, I get a null-pointer exception for someService. I've also output the value of someService to verify it is really null, which it is.
Edit: When I added a #Named("skldjfx") qualifier to the injection point, Weld complained the dependency is unsatisfied (in the validation phase), so that's a good sign. However, the field is still always null.
Servlet:
public class BlogServlet extends HttpServlet {
#Inject private SomeService someService;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println("Hello. " + someService.getSomeValue());
// \
// always null
}
}
SomeService class:
#ApplicationScoped
public class SomeService {
private String someValue = "some value";
public String getSomeValue() {
return someValue;
}
}
I've configured Weld's Listener in web.xml:
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
The listener is properly loaded because it logs its initialization message: org.jboss.weld.environment.servlet.Listener contextInitialized.
I've included (an empty) beans.xml in both war/WEB-INF and war/META-INF. I also tried it without META-INF. Maybe beans.xml isn't processed? Other contents in the WEB-INF folder (such as web.xml) are processed properly.
How can I verify if beans.xml is processed and/or fix SomeService not getting injected?
It looks like it's not possible to use CDI with GAE, because GAE's Jetty fork ignores jetty-web.xml, which is needed to specify the BeanManager. See this link and this link. Really strange GAE is not supporting the use of CDI.
Note that these links are really old, but so far I haven't found any evidence to the contrary.
Anyway, my next step will be to use Google's own dependency injection framework Guice. Using it with GAE is described here. I'd prefer CDI though.

Resources