RESTful service in Karaf without blueprint xml - java

I am new to Karaf, hence was looking for resources to create a project for RESTful web services using felix annotations and without the use of BundleActivator class(i mean by an actual class that needs to be written by me, but its ok if some compiler or maven plugin does the same for me) and blueprint xml file. So far I got success in the first part(BundleActivator part) which now after compilation auto creates my MANIFEST.MF with import and export statements, creates the relevant XML file for each component class, and packages it into a a nice jar bundle which works very well when I deploy it on Karaf container. But what is not working is the RESTful services. The bundle is deployed correctly, but the REST urls are not exposed and hence I am unable to access them.
Please help me in getting this done. I don't want to write an XML file which needs to be modified everytime there is an addition or deletion of a rest service.
Thanks

If you want to completely avoid blueprint then you should use cxf-dosgi. You simply annotate your rest service using jaxrs and publish it as an OSGi service with some special properties.
See the cxf-dosgi rest sample.
The example uses the standard DS annotation and the maven bundle plugin to create the DS component xml on the fly.
If you prefer to have blueprint at runtime then you can use the blueprint-maven-plugin. See this example.

I figured out a way to do so without using the CXF feature. That is, create a component class and in activate method get the object of ConfigurationAdmin and put the required context path against the jersy server process(using jersey publisher jar). Using this mehtod, I was able to deploy any rest/serlvet in Karaf without using blueprint.xml file. I hope this helps.

Related

not able to get the bean which is created in another 3rd party spring boot lib

I have a spring boot app in which I have added another library (in pom.xml).
This library is also a spring boot library which has created some beans and made the beans available using #Bean. The code snippet in 3rd party library is like this :
#Bean
public CustomObject customObject() {
return new CustomObject();
}
Now, I am using this library in my application, but I dont see this bean registered with my application.
I checked all the beans registered with application Context and also tried loading from application context. But no luck.
What am I missing here? The purpose of this 3rd party library is to check some config and create this bean, so if I have to manually create this bean, it takes away the whole purpose.
This is information is not enough, can you please share your pom file of library that contains CustomObject.
I need to see pom file build section code.
as suggested by #Rohit in comments, I missed to add the package of the class in the 3rd party lib jar under component scan. After adding the package under component scan, issue is resolved.

spring boot without tomcat in a standalone jar

I have a project structure with three jar files. All are loaded into one classpath and then get executed. I am using the spring core, jpa and hibernate. #Services/#Autowired are working fine, as well as Entities and Repositories (all on a mysql database).
Now I want that the project can send and receive messages over network/internet. So I asked some people how I could achieve this without breaking my current structure. And I was told that spring-boot is the architecture for me because I do not need a web server (tomcat or glassfish) for it.
But now I am not sure if this is correct because I did not find any sources that say the same thing. Because of that I tried implementing it in order to verify it myself.
The important changes I made to my project (all pom.xml files and my configuration class) can be found here: http://84.141.90.123:9910/
From what I read I need the #SpringBootApplication annotation for spring boot. This is a equivalent to #Configuration, #ComponentScan, #EnableAutoConfiguration, #EnableWebMvc.
The first two are already in my structure. But when I add the last two annotations, I get different errors:
When I add #EnableAutoConfiguration I get
Caused by: java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
When I add #EnableWebMvc I get
Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
From my bad english knollage, the #EnableWebMvc error seems to say that the application needs a web server (tomcat or glassfish).
So is the main statement wrong and I can not start spring boot without a web server?
Because I do not use any xml files and/or property files for spring (they did not worked), I only rely on java code based configuration for spring, jpa and hibernate. And therefore there are only very few tutorials/threads with help. Most of the time they just say add thi or add that to your xml but because I don't have them, it is a little pain in the ass.
Also I compile with aspectj, so I can not use the spring compile parent. And also I am not able to manipulate the main class/method, because the main class is in an outer jar file that is not programmed by me.
So concrete:
Can a spring boot application in a standalone jar run without a web server wrapping it?
If yes, what am I doing wrong? Am I missing a dependency, an annotation or a configuration?
If you want to receive messages over HTTP(ie run a REST API) then you need a web server.
If you just want to send messages over HTTP then you only need a HTTP client.
Spring-boot has the the option of running an embedded web server(tomcat by default), you don't need to run a separate application server.
To work out your issues with your build I would start with generating a project using spring initializr.
You can select the dependencies you want(try using the advanced version link at the bottom), and it will build a maven/gradle project for you with the right structure, build file and compatible dependencies.
Change :
public static void main(String[] args) {
SpringApplication.run(ActiveMqApplication.class, args);
}
to :
public static void main(String[] args) {
new SpringApplicationBuilder(ActiveMqApplication.class)
.web(WebApplicationType.NONE).run(args);
}

Adding custom nodetypes to Apache Sling WebApp

I'm trying to figure out a way to add custom nodetypes using a CND file to my Sling WebApp. I downloaded the WAR file and got it running but since all the code is already compiled (as .class files), I can't add code to read the CND file and add the custom nodetypes.
On a separate note, I do have Jackrabbit running and with it, I can use the JackrabbitNodeTypeManager or other ways to code reading a CND file and adding nodetypes. This works on my local repository that is not running on a server.
I want to be able to add new nodetypes to the Sling Web Application in a similar way. So I'll boil my questions down to:
Is there a way to code the addition of new nodetypes in the Sling WebApp?
How can I connect my Jackrabbit repository (local) to the Sling Web Application (on server) so that I can possibly explore adding custom nodetypes this way (as I'm doing on my Jackrabbit repo locally at the moment)?
I understand that Sling is a framework that uses Jackrabbit as a repo and provides REST-like services to work with the repository, but I imagine there's a way to add these custom nodetypes just like Jackrabbit allows.
Thanks.
Is there a way to code the addition of new nodetypes in the Sling WebApp?
This is documented at Declared Node Type Registration. What you need to do is
write the node type definition in CND format
place it in a bundle
reference the file in the manifest using the Sling-Nodetypes header
deploy the bundle to your Sling app

Same Package, Same Class in two Maven Projects a WAR and a JAR, classpath issue

I am having some classpath issue. I have a Web Application which is a web service. It uses JaxB and CXF. The web service has a dependecy of another JAR which is a Web Service Client. Now both the client and the service codes are generated by using wsdl2java plugin. The problem looks like this:
Parent WebService WAR
--PackageA
--ClassB
Dependency Jar
--PackageA
--ClassB
So both of them have the same package and the same class name and since these are generated by the plugin, it makes difficult to refactor one of the package so that they would not be identical.
The WebService calls the client and in client code initializes the parent classB from web service instead of the classB from web service client Jar. The only problem in this ClassB is that they have one method which takes differnet parameter, in one class B it takes, Date whereas in another classB it takes XmlGregorianCalendar. So while calling the client i am getting nosuchmethodexception.
Here is what i tried so far without luck:
1: In the Client jar i tried giving the full package and class name to initialize the ClassB
2: In the Client jar i tried wiring the classes using Spring bean and surprisingly it is still wiring the class from the webService instead of the client
3: In the web service ClassB, i tried adding the same method that takes the right parameter. This works partially but result in another exception which is not good.
Looking forward for your help. Thanks!
Solved the issue by passing extra args to wsdl2java plugin while generating classes from the wsdl as per user2880879 suggestion like this:
<extraarg>-p</extraarg>
<extraarg>http://www.example.com=mypackagename</extraarg>
I believe you are creating webservice using top down approach, means write java class first using jaxws annotations and then create wsdl using cxf maven plugin or ant, and use this wsdl to create client ?
If you are following this approach then you can provide binding file when you generate web service client code. click here to know what is binding file and how to write.
In this binding file you can specify package name you want to change for client code.

Call glassfish ejb from stand-alone application

So I have a simple ejb (#stateless) deployed on a glassfish 3.1 server.
I want to call it from a standalone application.
It's working great if I add the gf-client.jar into my run configuration.
But how can I do if I do not have that file (the server is in another machine) ?
I tried using
<dependency>
<groupId>org.glassfish.common</groupId>
<artifactId>glassfish-naming</artifactId>
<version>LATEST</version>
</dependency>
But I have
Exception in thread "main" javax.naming.NameNotFoundException: java:global
at com.sun.enterprise.naming.impl.TransientContext.resolveContext(TransientContext.java:252)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:171)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:58)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:95)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:233)
at javax.naming.InitialContext.lookup(Unknown Source)
at be.java.tuto.Application.main(Application.java:17)
Thanks.
EDIT:
I just needed to invoke an EJB deployed on GF from my Tomcat server and resurrected my dependencies. And because I dont want to keep them back for myself :)...
My IDE is Eclipse so I created an User Library containing all the files shown above.
Hope this solves your problem!
I was facing the same problem. For just wanting to invoke a GF session-Bean method I had to add the complete gf-client.jar to my clients classpath.
My problem was that this library is referencing almost the whole GF-libray-folder and even after a clean-up there were >15 referenced jars left which I had to add to my clients classpath.
For me I did't want this overhead so I decided to call the remote method via JAX-WS webservice.
The advantage of using webservises is that it is very easy to add webservice capability to an already existing session-bean by annotating the bean-class with #WebService.
After publishing the bean to the appserver you're able to view your deployed endpoint and getting the WSDL. With this you can generate your webservice-stubs automatically by using the wsimport-tool shipped with your JDK and use this generated files in yor client to invoke the remote method.
See example here.
Once created those files are portable and can be used in any client.
So if your willing to change the way your client calls the remote method this would be a portable, lightweight (except of a bit more http overhead) and easy to implement alternative.
P.S.
You don't lose the ability of invoking your method via EJB-call.
Hope this helped, have Fun!

Categories