How to build runnable JAR using Javalite framework as standalone http? - jar

As questioned, how to build runnable JAR using Javalite framework?
Javalite doesn't have known entry point / main class. I browse some of the examples but not found any clue.
This jar will run as stand-alone on server using java -jar command.
Below snippet of my plugin on pom.xml file
Packaging
<modelVersion>4.0.0</modelVersion>
<groupId>org.javalite</groupId>
<artifactId>activeweb-simple</artifactId>
<packaging>jar</packaging>
<version>1.1-SNAPSHOT</version>
<name>ActiveWeb Example WebApp</name>
Plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- Jar file entry point -->
<mainClass>com.company.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
And the Application.java,
public class Application {
public static void main(String[] args) throws Exception {
String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
String webPort = System.getenv("PORT");
if(webPort == null || webPort.isEmpty()) {
webPort = "8081";
}
tomcat.setPort(Integer.valueOf(webPort));
StandardContext ctx = (StandardContext) tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
System.out.println("configuring app with basedir: " + new File("./" + webappDirLocation).getAbsolutePath());
File additionWebInfClasses = new File("target/classes");
WebResourceRoot resources = new StandardRoot(ctx);
resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes",
additionWebInfClasses.getAbsolutePath(), "/"));
ctx.setResources(resources);
tomcat.start();
tomcat.getServer().await();
}
}
Note : I'm currently using tomcat as embedded http-server to enable the JAR file run as stand-alone. But, Javalite ActiveWeb probably has a way for this.

You can build any number of different types of JavaLite projects, such as standalone that use some features: JavaLite HTTP, ActiveJDBC, JavaLite Async, etc. In addition, if you want to build a web application, you also will need ActiveWeb.
Here is a list of examples from the JavaLite repo:
ActiveJDBC:
https://github.com/javalite/standalone-example
https://github.com/javalite/simple-example
https://github.com/javalite/ant-example
https://github.com/javalite/activejdbc-gradle
https://github.com/javalite/multiple-db-example
ActiveWeb:
https://github.com/javalite/activeweb-simple
https://github.com/javalite/kitchensink
https://github.com/javalite/activeweb-secure
https://github.com/javalite/activeweb-bootstrap
https://github.com/javalite/activeweb-lessc
Every example app has a README file you can read to see what the example is for.
In order to start any project, just clone a repo, get it running then start modifying it to your liking.
Additionally, pay attention to the Releases page http://javalite.io/releases and keep your dependencies up to date.

Related

openapi.yaml not generated successfully - Swagger Doc does not open for Windows machines

So I am working on a spring-mvc project, which suddenly started giving this issue when installed on Windows machines only. It's a thick client app.
When trying to access the swagger docs, following error comes :
The logs show following error in the stacktrace :
2022-04-20 04:15:44.821utc WARN Configuration,main:117 - couldn't read inflector config from resource stream
2022-04-20 04:15:44.821utc WARN Configuration,main:131 - couldn't read inflector config from system property
2022-04-20 04:15:44.853utc WARN OpenAPIV3Parser,main:91 - Exception while reading:
io.swagger.v3.parser.exception.ReadContentException: Unable to read location `openapi.yaml`
at io.swagger.v3.parser.OpenAPIV3Parser.readContentFromLocation(OpenAPIV3Parser.java:238) ~[swagger-parser-v3-2.0.27.jar:2.0.27]
at io.swagger.v3.parser.OpenAPIV3Parser.readLocation(OpenAPIV3Parser.java:87) ~[swagger-parser-v3-2.0.27.jar:2.0.27]
..
..
2022-04-19 17:19:16.980utc ERROR [swagger-inflector],http-nio-8080-exec-8:175 - Allocate exception for servlet [swagger-inflector]
*java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.OpenAPI.getComponents()" because "openAPI" is null
at io.swagger.oas.inflector.utils.ExtensionsUtil.removeExtensions(ExtensionsUtil.java:26) ~[swagger-inflector-2.0.6.jar:2.0.6]
at io.swagger.oas.inflector.OpenAPIInflector.getExposedAPI(OpenAPIInflector.java:543) ~[swagger-inflector-2.0.6.jar:2.0.6]*
at io.swagger.oas.inflector.OpenAPIInflector.init(OpenAPIInflector.java:139) ~[swagger-inflector-2.0.6.jar:2.0.6]
at io.swagger.oas.inflector.OpenAPIInflector.<init>(OpenAPIInflector.java:117) ~[swagger-inflector-2.0.6.jar:2.0.6]
at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
at
OpenAPIInflector.getExposedAPI reads swaggerURL location from inflector.yaml file. For some reason on windows, configuration is not picking up openapi.yaml file or corresponding openapi.json file as shown in the screenshot. xxx-openapi.yaml is something defined inside inflector.yaml which in my understanding is being used to generate an openapi.yaml file. In MacOs/local setup I can see this file getting generated and the docs coming up fine.
Please help debug, what the potential cause could be. Permissions are fine on the system this tool is running for inflector.yaml inside classes folder?
here is how the inflector.yaml is defined.
swaggerUrl: xxx-openapi.yaml
xxx-openapi.yaml & inflector.yaml are present in
src/main/resources/
I am also wondering if windows OS is not able to read the files from this path properly. Bases on other posts I have already tried different URLs such as following but they did not work for me.
http://windows-machine-ip:8080/swagger-ui/
http://windows-machine-ip:8080/swagger-ui/index.html
http://windows-machine-ip:8080/v3/api-docs/swagger-ui.html
Note**
openapi: 3.0.0
Dependencies :
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-inflector</artifactId>
<version>2.0.6</version>
</dependency>
Please guide. I am new to this project as well as swagger on spring-mvc. I will be happy to read about stuff which can lead me to fix this. Not looking for a readymade solution but I have tried almost all relevant solutions across multiple forums and hence the post as I am still not able to find the root cause to this. Also I cannot change the existing implementations (like writing it all from scratch) hence I am here more to understand the root cause.
I'm just installing OpenAPI 3 on Spring Core 5.3.18 (Not Boot) projetc :
1/`<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.6.7</version>
</dependency>`
2/ Configurer :
#Configuration
#EnableOpenApi
public class SwaggerConfig {
private static final Logger log = LoggerFactory.getLogger(SwaggerConfig.class);
private static String line = "=".repeat(100);
#Bean
public Docket api(ServletContext servletContext) {
log.info(line);
log.info("Docket swagger called : {} , name :{} ", servletContext.getContextPath(), servletContext.getContext("/rs"));
log.info(line);
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
;
}
3/ WebConfigurer :
`
#Configuration
#EnableWebMvc
public class WebConfigurer implements WebMvcConfigurer {
private static final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.resourceChain(false);
}`
4/ URL of Swagger UI is :
[root path]/v3/api-docs for documentation
[root path]/swagger-ui/index.html
Hope that help ;-)

RegisterType from unity configuration file

I am migrating from Prism 4 to Prism 7.1, I cannot seem to find the ConfigureContainer method has been removed from the latest Prism release. In the past, I had used this method to load the unity configuration from the file system.
with the latest version of the Prism library, this appears not to be possible.
I have already explored the option of ModuleConfiguration, which to me does not provide the ability to inject dependencies through a configuration file in the same way.
Is there an alternate approach for this, where I can provide type registration through a configuration file.
Here is how I did it in the past:
1- In the BootStrapper following method was overridden:
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)config.GetSection("unity");
if (section != null)
{
section.Configure(Container);
}
}
2- Add config section in the app.config file:
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration" />
3- Add a unity config file which looks like:
<unity xmlns="schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Unity.FactoryConfig.FactoryConfigExtension, Unity.FactoryConfig"/>
<alias alias="Singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity"/>
<alias alias="ConfigFactory" type="Vms.Pt.Common.DependencyInjection.ComponentBuilder.ConfigClassFactory`1, Vms.Pt.Common.DependencyInjection.ComponentBuilder"/>
<container>
<!--Modal/popup provider service-->
<register type="IPopupService, GUI.Infrastructure"
mapTo="Services.PopupService, GUI.Infrastructure">
<lifetime type="Singleton"/>
</register>
</container>
</unity>
It's now called RegisterTypes in the PrismApplicationBase. Just override that and do whatever you would have done in ConfigureContainer.
Hint: if you don't like the "abstraction" Prism 7 put between you and IUnityContainer, you can call GetContainer() on the IContainerRegistry (it's an extension method) to get the hidden IUnityContainer instance.
Thanks Haukinger. I had to downgrade the Unity.Abstractions nugget to V3.31 to make the configuration work with prism 7. It does not work with the latest version of the Nugget.

PaxExam tests configured with wrappedBundle()

For the configuration in PaxExam (version 4) we're using wrappedBundle() as you can see here:
wrappedBundle(mavenBundle().groupId("com.github.tomakehurst").artifactId("wiremock-jre8").versionAsInProject()),
Because we want to create an OSGi bundle out of an ordinary jar.
Then in order the wrap mechanism can be used we have to install the wrap feature:
features(karafStandardRepo, "wrap"),
The problem is when it comes to install wrappedBundle() the wrap feature is not yet there. How can I assure in the PaxExam configuration wrappedBundle() is executed only after the wrap feature is there and ready for use? The Karaf distribution we are using in this test is version 4.0.7.
Thanks for help,
Kladderradatsch
Yes, indeed we had to wrap the WireMock bundle generation by the PaxUrl Wrap mechanism into a separate feature file:
<features name="wiremock-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<feature name="wiremock" version="${project.version}">
<feature prerequisite="true">wrap</feature>
<bundle>
wrap:mvn:com.github.tomakehurst/wiremock-jre8-standalone/2.21.0$Bundle-ClassPath=.
</bundle>
</feature>
</features>
Very important is here to configure the XML namespace properly, namely to address version v1.4.0 otherwise prerequisite is of no use. A further pitfall I stepped in before was not taking the standalone version of WireMock.
Then in the PaxExam configuration I have just installed the feature:
features(maven().groupId("com.company.wiremock").artifactId("wiremock-feature").type("xml").classifier("features").version("1.0.0-SNAPSHOT"), "wiremock"),
When it comes to initialize the WireMockServer in your tests, in order the resources in the new generated WireMock-Bundle can be loaded via ClassLoader.getResource() (internal stuff of that library), you have to do this here in your test otherwise the Bundle-Classloader of that WireMock-Bundle is not used:
#BeforeClass
public static void setup() {
ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(WireMockClassRule.class.getClassLoader());
wireMockServer = new WireMockServer(options().dynamicPort());
wireMockServer.start();
} finally {
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}
#AfterClass
public static void end() {
wireMockServer.stop();
}
You could put this in a JUnit #ClassRule for encapsulation.

How to run standalone TestNG project from jar/bat/

I have a TestNG project. Don't have any main class, currently it is running like "Run As TestNG".
I want to export it as runnable jar or jar so that any one can just hit a command from command line and test cases start running.
Could any one help me out in this? or suggest any other way to deliver the code in runnable form...
I am not using ant or maven.
Thanks
I seem to have found the solution after a bit of googling. This works fine in Eclipse (Juno).
Say, you have a TestNG file named 'Tests.java'. As you rightly pointed out, there won't be a class with main method.
So, we have to create a new Java class file under the same package. Let us name it 'MainOne.java'. This will have a class with main method.
Here is the code you need:
import com.beust.testng.TestNG;
public class MainOne {
public static void main(String[] args) {
TestNG testng = new TestNG();
Class[] classes = new Class[]{Tests.class};
testng.setTestClasses(classes);
testng.run();
}
Run the 'MainOne.java' as a Java application. Then right click on the package -> Export -> Runnable Jar [Choose 'MainOne' as Launch Configuration] -> Finish.
My current understanding is that, in order to benefit from the parallel niftiness of TestNG, one should use the static main method in org.testng's jar file when running the Java class from the command line rather than from inside Eclipse IDE.
The issue then becomes classpath, which defines how java finds all the JAR files. I found http://javarevisited.blogspot.com/2012/10/5-ways-to-add-multiple-jar-to-classpath-java.html to be most useful because it has the * wildcard mentioned --- VERY helpful when you need to reference all the jar files required for Selenum + TestNG + custom test suites.
This is my current Windows BAT file, and it works. ADV.jar contains my custom class but no main method.
setlocal
set r=d:\Apps\Selenium\
cd /d %~dp0
java -classpath %r%Downloaded\*;%r%MyCompany\ADV.jar; org.testng.TestNG .\testng-customsuite-adv.xml
pause
All the JAR files that I downloaded from public places went into my d:\Apps\Selenium\Downloaded folder. I put my custom ADV.jar file in d:\Apps\Selenium\MyCompany to keep it separate.
I created my ADV.jar file from Eclipse using Export Jar file and ignored warnings about a missing main method.
Aside: while this https://stackoverflow.com/a/16879386/424855 was very intriguing, I could not figure out how to make that work.
Here is the better way to do it.
You can just create a main method which will have list of all test classes to be executed as follows:
public static void main(String[] args) {
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses(new Class[] { test_start.class });
testng.addListener(tla);
testng.run();
}
Here is the reference URL from the official testng website.
Run the MainOne.java as a Java application. Then right click on the package -> Export -> Runnable Jar [Choose MainOne as Launch Configuration] -> Finish.

Looking up a Remote Bean, getting a EjbNamingContext in JBoss 7.1

I have a Maven project, in which I want to try integration-testing an EAR sub-module.
In the integration-test submodule, I do the following:
Properties env;
Context ctx;
env = new Properties();
env.setProperty( "java.naming.factory.initial", "org.jboss.naming.remote.client.InitialContextFactory");
env.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
env.setProperty( "java.naming.provider.url", "remote://localhost:4447");
env.put(Context.SECURITY_PRINCIPAL, "jboss-user");
env.put(Context.SECURITY_CREDENTIALS, "*******");
ctx = new InitialContext( env );
IBMPFacadeRemote bmpFacade = ( IBMPFacadeRemote ) ctx.lookup( "ejb:DeDomain-ejb-1.0-SNAPSHOT/BMPFacade!de.domain.service.IBMPFacadeRemote");
bmpFacade.executeBMPProcess( model1, model2);//model1 & model2 are some entities
The problem: when calling mvn integration-test it ends up with the following Exception
java.lang.ClassCastException: org.jboss.ejb.client.naming.ejb.EjbNamingContext cannot be cast to de.domain.service.IBMPFacadeRemote
Could someone help me to solve this problem? Are there any possibilities to integration-test this using a Local Bean (the maven project uses the failsafe-plugin)?
It is now hard to say what exactly solved the problem, but I will try to mention all made changes that solved the problem.
Added to the pom.xml the dependencies
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-ejb-client-bom</artifactId>
<version>7.1.1.Final</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-jms-client-bom</artifactId>
<version>7.1.1.Final</version>
<type>pom</type>
</dependency>
Changed the JNDI lookup as follows (after changing the deployed name of the EAR&EJB projects)
IBMPFacadeRemote bmpFacade = ( IBMPFacadeRemote ) ctx.lookup( "ejb:DeDomain-ear/DeDomain-ejb//BMPFacadeBean!de.domain.service.IBMPFacadeRemote");
Got rid of the EJB maven plugin from the EJB Project & of some other resources, like jndi.properties
Probably it is worth mentioning, that the Properties instance remained the same as in the stated in the question.
The JNDI Properties are looking strange for me. I was always successfull with the following Properties for JBoss:
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
jnp.socket.Factory=org.jnp.interfaces.TimedSocketFactory
May be you should double check them.

Resources