Adding OSGi fragment bundles in Felix servletbridge war - osgi

I am trying to create war hosting OSGi bundles. The complete configuration should be able to host WAB bundles, and now I try to integrate pax-web-extender-war for that.
It requires some dependencies like slf4j-api and slf4j-log4j12 and here is the problem: I always get this exception:
org.osgi.framework.BundleException: Fragment bundles can not be started.
at org.apache.felix.framework.Felix.startBundle(Felix.java:1782)
because slf4j-log4j12 is really a fragment bundle. I assumed Felix should cope with this but it does not. So I tried to move this jar to WEB-INF/lib but then wiring fails as osgi cannot resolve it as a bundle.
So,
Where should I put fragment bundles ?
Should it be somehow configured in framework.properties ?
is Apache Felix even capable of working with fragment bundles ?
Following is current layout of the war (note that it is based on felix http bridge sample):
.
└── WEB-INF
├── bundles
│   ├── commons-fileupload-1.2.2.jar
│   ├── commons-io-2.4.jar
│   ├── hello-wab-1-SNAPSHOT.war
│   ├── org.apache.felix.http.bridge-2.2.0.jar
│   ├── org.apache.felix.http.samples.filter-2.2.0.jar
│   ├── org.apache.felix.webconsole-4.0.0.jar
│   ├── pax-web-api-2.1.0.jar
│   ├── pax-web-extender-war-2.1.0.jar
│   ├── pax-web-spi-2.1.0.jar
│   ├── slf4j-api-1.6.6.jar
│   ├── slf4j-log4j12-1.6.6.jar
│   └── wrapper-json-1-SNAPSHOT.jar
├── classes
│   └── org
│   └── apache
│   └── felix
│   └── http
│   └── samples
│   └── bridge
│   ├── FrameworkService.class
│   ├── ProvisionActivator.class
│   └── StartupListener.class
├── framework.properties
├── lib
│   ├── org.apache.felix.framework-4.0.3.jar
│   ├── org.apache.felix.http.proxy-2.2.0.jar
│   ├── org.apache.felix.webconsole-4.0.0.jar
│   ├── org.osgi.compendium-4.3.0.jar
│   └── wrapper-json-1-SNAPSHOT.jar
└── web.xml

I suggest adding pax-logging to your bundles, it'll keep away the pain of logging in the OSGi world. Pax-Logging
For the fragment-bundles you just need to add them to the usual bundles. I'd say in your setup probably in the bundles folder. Since it's a fragment bundle the Exception you get is right, it's not a "startable" bundle. It will only resolve and hopefully attached to the hosting bundle.
By the way, Felix is capable of working with fragment bundles :)

Related

How to include another module in dependency of my gradle project, but exclude certain directories

We have a gradle multi module project. api-1 is a dropwizard legacy project, and api-2 is the spring-boot project.
root-project
├── api-1
│   ├── build.gradle
│   ├── config
│   ├── libs
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   └── resources
│   │   │   ├── META-INF
│   │   │      └── services
│   │   │      └── org.hibernate.integrator.spi.Integrator
├── api-2
│   ├── build.gradle
│   └── src
│   ├── main
│   │   └── resources
│   └── test
│   └── resources
├── gradle
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
We have our entities in api-1 which we are trying to use in api-2. So in api-2's build.gradle file I included implementation project(':api-2'). It feels a lil bit coarse to import the module along with all its transitive dependencies in to this module; but for now I does the trick.
The Issue:
The problem here is that api-1 has hibernate 5.2 dependency and it has this org.hibernate.integrator.spi.Integrator file in the resource folder. It references org.hibernate.jpa.event.spi.JpaIntegrator. Apparently this class was removed from hibernate from version 5.3 (ref: https://github.com/hibernate/hibernate-orm/blob/5.3/migration-guide.adoc#jpaintegrator-removed )
Now when I run (task bootRun) my api-2 module, I it fails with the below exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.util.ServiceConfigurationError: org.hibernate.integrator.spi.Integrator: Provider org.hibernate.jpa.event.spi.JpaIntegrator not found
What I Already Tried:
However if I delete this file (org.hibernate.integrator.spi.Integrator) from api-2, then api-2 runs and also api-1 seems to be running without any issues. But api-1 is a legacy project, and I am wary that it is wreck-less to simply remove the file without understanding it's implication fully.
I am trying to figure out if there is a safer way to get around this issue; maybe exclued that particular file in api-2. Or any better alternative?

JSPs with Spring Boot

I have been working on a spring-boot project initialized with spring initialzr. The generated package has no /webapp directory, hence had to add /webapp directory. I have read from spring documentation that spring detects static files from /static,resources. I have placed 3 different index.jsp to test which one gets displayed by my controller. Below are the code snippets.
Directory Tree:
├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │   └── databasedisplay
│   │   │   └── app
│   │   │   ├── AppApplication.java
│   │   │   ├── config
│   │   │   │   ├── WebAppInitializer.java
│   │   │   │   └── WebConfig.java
│   │   │   ├── controller
│   │   │   │   ├── HomeController.java
│   │   │   │   └── IndexController.java
│   │   │   ├── repository
│   │   │   └── ServletInitializer.java
│   │   ├── resources
│   │   │   ├── application.properties
│   │   │   ├── index.jsp
│   │   │   ├── static
│   │   │   │   └── index.jsp
│   │   │   └── templates
│   │   └── webapp
│   │   └── WEB-INF
│   │   └── views
│   │   └── index.jsp
│   └── test
│   └── java
│   └── com
│   └── databasedisplay
│   └── app
│   └── AppApplicationTests.java
└── target
├── classes
│   ├── application.properties
│   ├── com
│   │   └── databasedisplay
│   │   └── app
│   │   ├── AppApplication.class
│   │   ├── config
│   │   │   ├── WebAppInitializer.class
│   │   │   └── WebConfig.class
│   │   ├── controller
│   │   │   ├── HomeController.class
│   │   │   └── IndexController.class
│   │   └── ServletInitializer.class
│   ├── index.jsp
│   └── static
│   └── index.jsp
├── generated-sources
│   └── annotations
├── generated-test-sources
│   └── test-annotations
├── maven-status
│   └── maven-compiler-plugin
│   ├── compile
│   │   └── default-compile
│   │   ├── createdFiles.lst
│   │   └── inputFiles.lst
│   └── testCompile
│   └── default-testCompile
│   ├── createdFiles.lst
│   └── inputFiles.lst
└── test-classes
└── com
└── databasedisplay
└── app
└── AppApplicationTests.class
index.jsp (in '/resources')
<html>
<head></head>
<body>
<h1>This is the body of the sample view in /resources</h1>
</body>
index.jsp (in '/static')
<html>
<head></head>
<body>
<h1>This is the body of the sample view in /static</h1>
</body>
</html>
index.jsp (in '/WEB-INF/views/')
<html>
<head></head>
<body>
<h1>This is the body of the sample view in WEB-INF/views</h1>
</body>
</html>
Controller
#Controller
public class IndexController {
#RequestMapping(value = "/indexA", method = RequestMethod.GET)
public String index() {
return "index";
}
}
Configuration Classes
WebConfig.java
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver
= new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable("testServlet");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/").setCachePeriod(3600)
.resourceChain(true).addResolver(new PathResourceResolver());
}
}
WebInitializer.java
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.scan("com.databasedisplay.app");
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container.addServlet("mvc", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
The issue is when I run with mvn spring-boot:run or mvn clean package spring-boot:run the \target directory as shown in the directory tree has no index.jsp from \WEB-INF\views\ (in fact the target directory doesn't have a WEB-INF directory at all). But I still get the following output when I curl http://localhost:8080/indexA :
This is the body of the sample view in WEB-INF/views
Can someone explain how the view resolver even maps the view names to the corresponding views? (I have looked into InternalResourceViewResolver and how to set prefixes and suffixes but that still does not explain how it can render a jsp when it is not in target)
Can someone point out to the differences between mvn spring-boot:run and mvn clean package spring-boot:run as in the latter there is WEB-INF directory in the target.
Why am I getting index.jsp corresponding to /WEB-INF but not other views on curl?
JSP's are part of legacy Java Enterprise applications and are not the core of Spring Boot/MVC and it's more modern Template Engine approach (although Spring is based on Java EE). If you have any good reason to use JSP's, it could work. But with Spring, the MVC approach/implementation is to use the more modern template engines with technologies like Thymeleaf, FreeMarker, Groovy Markup, and Mustache.
Question 1 If you have configured your pom.xml correctly, you can use different starters to configure how your application is deployed/run. JSP's are not a standard solution for Spring and should be configured seperately, it needs to be configured so that it will compile the JSP's into their respective location so that Tomcat reads it from the webapps folder. To compile and render JSP's your pom.xml needs both spring-boot-starter-web and tomcat-embed-jasper including the tag <scope>provided</scope>.
Question 2 Spring comes with an embedded Tomcat server (spring-boot-starter-web). When you run mvn spring-boot:run it will start a Tomcat server and deploy your Spring Boot application on the Tomcat localhost:8080. mvn clean, before spring-boot:run, just deletes the output of a build by deleting the build directory.
Question 3 Each .HTML template or .JSP file have their respective location in the project before compiling, so therefore some .JSP's are not compiled in your folders.
A Java Enterprise application and it's corresponding JSP's use a different project structure than Spring: All JSP's will be compiled from the "src/main/webapp/WEB-INF/jsp/" if you have the right dependencies and run spring-boot:run. If you manually create a project, through compiling by cmd -jar, you should include your JSP's in the "/webapp/" folder and the Java.classes in WEB-INF/classes/MyServlet.class.
By using, for instance Thymeleaf (spring-boot-starter-thymeleaf), if you build your artifacts the IDE will compile templates from /resources/templates and work from there on your MVC project, where you can integrate your REST controllers seamlessly.
Tomcat stays pivotal in how your enterprise application is deployed, only that you need to adjust your project in Spring so that it will map and compile the right files into the .WAR before deploying.
My advice would be, for MVC, to use the template engines instead of the legacy JSP's. of course, there will use cases for JSP's inside a Spring project but it requires a differect structure and dependencies.

Correct directory structure for Puppet RSpec testing

I'm having some issues creating unit tests for my Puppet control repository.
I mostly work with roles and profiles with the following directory structure:
[root#puppet]# tree site
site
├── profile
│   ├── files
│   │   └── demo-website
│   │   └── index.html
│   └── manifests
│   ├── base.pp
│   ├── ci_runner.pp
│   ├── docker.pp
│   ├── gitlab.pp
│   ├── logrotate.pp
│   └── website.pp
├── role
│   └── manifests
│   ├── gitlab_server.pp
│   └── nginx_webserver.pp
Where do I need to place my spec files and what are the correct filenames?
I tried placing them here:
[root#puppet]# cat spec/classes/profile_ci_runner_spec.rb
require 'spec_helper'
describe 'profile::ci_runner' do
...
But I get an error:
Could not find class ::profile::ci_runner
The conventional place for a module's spec tests is in the module, with the spec/ directory in the module root. So site/profile/spec/classes/ci_runner_spec.rb, for example.
You could consider installing PDK, which can help you set up the structure and run tests, among other things.

Configure Intellij Idea to import generated files

I'm having trouble to import a generated package with Intellij, however without any changes to the default settings it works on Eclipse.
Here is my architechture:
├── build.properties
├── pom.xml
├── README.md
├── src
│   ├── main
│   │   ├── java
│   │      └── mypackage
│   └── test
└── target
├── classes
│ └── mypackage
| └── generated
├── generated-sources
├── generated-test-sources
├── APP.jar
└── test-classes
I have most of my classes in com.mypackage however some of them are generated in
└── target
├── classes
└── mypackage
named as com.mypackage.generated and i have to use these classes in com.mypackage:
├── src
├── main
├── java
└── mypackage
However intellij cannot resolve symbol generated when I'm doing
import com.mypackage.generated
I tried to make it work by looking at the project structure/modules/dependencies menu but it seems to be for external modules. How can I do this ?
Actually it was very simple, I only was about marking classes as sources root. I don't know why marking generated as sources root did not work.

Gradle plugin packaging - Why is plugin unexpectedly applied?

So I have:
buildSrc/
├── build.gradle
└── src
├── main
│   ├── groovy
│   │   └── build
│   │   ├── ExamplePlugin.groovy
│   │   └── ExampleTask.groovy
│   └── resources
│   └── META-INF
│   └── gradle-plugins
│   └── build.ExamplePlugin.properties
└── test
└── groovy
└── build
├── ExamplePluginTest.groovy
└── ExampleTaskTest.groovy
Question:
It seems like build.ExamplePlugin.properties maps directly to the build.ExamplePlugin.groovy. Is this the case? Seems terribly inefficient to have only one property in the file. Does it have to be fully qualified, i.e. does the name have to exactly match the full qualification of the class?
Now in the example, I see:
project.pluginManager.apply 'build.ExamplePlugin'
...however if I have that in my test, I get an error to the effect that the simple task the plugin defines, is already defined.
Why bother with test examples that require 'apply' when that is inappropriate for packaging?

Resources