How to execute a jar file on jboss7 startup? - module

I have a simple java class which displays "waiting" text on execution , in "TMSCore" java project.
package com.stock.bo;
public class example {
/**
* #param args
*/
public static void main(String[] args) {
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("================================> waiting");
}
}
I have created TMSCore.jar and have set this example.class as entry point ,of my jar file.
Then i have created a module for this project in C:\Jboss\jboss-as-7.1.1\modules\org\tms\main , and pasted the jar in the same path
then i have created module.xml and pasted in the same path
module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.tms">
<resources>
<resource-root path="TMSCore.jar"/>
</resources>
</module>
then i have created a jboss-deployment-structure.xml in my webproject/web-inf directory
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.tms"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
when i start the server with my war containing above jboss-deployment-structure.xml, in my console its showing deployed TMSCore.jar
but my "waiting" text in my jar is not displayed on console
my requirement is i should get "================================> waiting" on my console once jboss is started up
or else can any one can suggest how to make a jar to execute on starting jboss server?
BTW i am using JBOSS7.1

If I am right it's because JBoss doesn't execute a library, it only loads the classes contained in the jar file. So putting a main function and generating an executable jar will not help.
If your goal is to have an global module on the server, I suggest you these modifications:
Create the module (as you have already done)
Declare it as dependency in jboss-deployment-structure.xml (as you have already done)
Declare it as global module on the server, so it will be loaded only once by JBoss. Edit the configuration file standalone.xml and modify the section:
<subsystem xmlns="urn:jboss:domain:ee:1.0">
<global-modules>
<module name="org.tms" />
</global-modules>
</subsystem>
Now you have a module that have classes loaded only once. I you need to have only one instance of your Example class, the I suggest you to use an singleton:
public class Example {
// The only one instance
private static Example instance;
// Private constructor to avoid creation of other instances of this class
private Example()
{
System.out.println("================================> waiting");
}
public static Example getInstance()
{
if(instance == null)
{
instance = new Example();
}
return instance;
}
}
Then to use it in all projects on the server
Example ex = Example.getInstance();
will give you back the existing instance (or create one the first time).
Notice: I can't try, so no guarantee that that will work.
Edit: Maybe a small modification of the Example class can also make it run during the classes loading:
public class Example {
// The only one instance
private static Example instance = new Example();
// Private constructor to avoid creation of other instances of this class
private Example()
{
System.out.println("================================> waiting");
}
public static Example getInstance()
{
return instance;
}
}
Again: not tested.

You can't run a jar, but you can execute a startup method in a singleton.
#Startup
#Singleton
public class FooBean {
#PostConstruct
void atStartup() { ... }
#PreDestroy
void atShutdown() { ... }
}
This will happen at application start up and shutdown. I'd call the function you need from there.
See http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html

Related

Cannot migration from old 3.4.2 keycloak to latest version

I'm in charge of the migration of an old keycloak ( 3.4.2 ) to the latest version. I already migrated the database and the template.
The last thing that poses problem is custom providers for Account and Login.
I have two custom providers that extends :
FreeMarkerAccountProviderFactory
FreeMarkerLoginProviderFactory
At first, no providers was loaded at the starting of keycloak in version > 4.x. I investigate, and i found that override the default getId() method to return a value other than the default "freemarker" makes keycloak load them again.
But after that if i try to access the login page, i got a nullpointer exception on org.keycloak.services.resources.account.AccountFormService.init(AccountFormService.java:139)
Any idea ?
Edit : spi in provider are declared in META-INF/services and provider in standalone.xml
Edit 2 : I share the loginFormProvider as it as the same problem, trigger the same error but it less complicated in it's implementation
public class KeycloakFreeMarkerLoginFormsProvider extends FreeMarkerLoginFormProvider {
public KeycloakFreeMarkerLoginFormsProvider(KeycloakSession session, FreeMarkerUtil freeMarker) {
super(sesssion, freeMarker);
}
public Response createResponse(LoginFormsPages page) {
List<Foo> foo = // loading foo entities
List<Bar> bar = // loading bar entities
super.attributes.put("foo", foo);
super.attributes.put("bar", bar);
return super.createResponse(page);
}
}
public class KeycloakFreeMarkerLoginProviderFactory extends FreeMarkerLoginFormsProviderFactory {
private FreeMarkerUtil freeMarker;
public KeycloakFreeMarkerLoginProviderFactory() {
super();
}
#Override
public LoginFormsProvider create(KeycloakSession session) {
return new KeycloakFreeMarkerLoginFormsProvider(session, this.freeMarker);
}
#Override
public void init(Config.Scope config) {
this.freeMarker = new FreeMarkerUtil();
}
#Override
public void close() {
this.freeMarker = null;
}
/* Without getId() or with a value at freeMarker, the provider
is not load. With other value, get NPE */
#Override
public String getId() {
return "custom.provider";
}
}
Based on the comments chain, it appears that the problem is that the provider is not getting picked up by Keycloak. You have a couple of options for bundling a custom provider with Keycloak: as a module, or as a deployed war/ear/jar in the deployments directory.
Here's how to do it as a module:
You'll need to add some configuration (module.xml), and your jar, to the modules directory structure. It should look like something like this:
(keycloak root)
|- modules
|- system
|- layers
|- keycloak
|- com
|- yourcompany
|- yourmodule
|- main
|- your-module-name.jar
|- module.xml (see below)
Your module.xml should look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<module name="com.yourcompany.yourmodule" xmlns="urn:jboss:module:1.6">
<resources>
<resource-root path="your-module-name.jar"/>
</resources>
<dependencies>
<!-- whatever module dependencies you need go here -->
<!-- these are just an example; you may or may not need them -->
<module name="org.jboss.logging" />
<module name="org.keycloak.keycloak-core"/>
<module name="org.keycloak.keycloak-services"/>
<module name="org.keycloak.keycloak-server-spi"/>
<module name="org.keycloak.keycloak-server-spi-private"/>
</dependencies>
</module>
Additionally, you'll need to configure standalone.xml and/or possibly standalone-ha.xml depending on your scenario (The default Keycloak Docker image uses -ha.xml by default). The pertinent section should look something like this:
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
<web-context>auth</web-context>
<providers>
<provider>
classpath:${jboss.home.dir}/providers/*
</provider>
<!-- add this -->
<provider>
module:com.yourcompany.yourmodule
</provider>
<!-- end add -->
</providers>
<master-realm-name>master</master-realm-name>
<scheduled-task-interval>900</scheduled-task-interval>
...
</subsystem>
Lastly, like you mention, you'll need the correct config in your META-INF/services directory: a file with the fully qualified classname of the ProviderFactory as defined by the SPI, with one line containing the fully qualified classname of your implementation. In your case, the file should be called org.keycloak.forms.login.LoginFormsProviderFactory and its value should be one line: (com.yourpackage).KeycloakFreeMarkerLoginProviderFactory
If it's picked up, you should be able to see it listed in the providers config in the admin UI. To view, log in to the admin console, click on your username in the upper right, and select "Server Info", then click on the "Providers" tab. You should see your provider listed under "login".

CDI doesn't work in a simple adapter

I've added the CDI feature to the server.xml file<feature>cdi-1.2</feature>.
My maven module contains the beans.xml inside the <module_name>/src/main/resources/META-INF folder.
This is the beans.xml content:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
But when I use the #Inject annotation it doesn't work, my bean is always null.
Code:
package ch.webapp.presentation;
...
#Path("/test/")
public class MyController {
#Inject
private MyService myService;
#GET
#Path("/foo/{count}")
#OAuthSecurity(scope = "login")
#Produces("application/json")
public Response news(#PathParam("count") int count) {
return Response
.ok(myService.getBar(count))
.build();
}
}
EDIT:
That's my bean
package ch.webapp.service;
...
#RequestScoped
public class MyService {
public String getBar(int count) {
return "foo";
}
}
I initialize jax-rs by extended the MFPJAXRSApplication class
package ch.webapp;
...
public class AccountApplication extends MFPJAXRSApplication {
#Override
protected void init() throws Exception {
}
#Override
protected void destroy() throws Exception {
}
#Override
protected String getPackageToScan() {
return getClass().getPackage().getName();
}
}
Environment details:
Launching mfp (WebSphere Application Server 8.5.5.8/wlp-1.0.11.cl50820151201-1942) on Java HotSpot(TM) 64-Bit Server VM, version 1.8.0_172-b11 (en_CH)
Console Product version: 8.0.0.00-20180717-175523
What's wrong?
First it seems that websphere jax-rs implementation does not integrate jax-rs resources automatically unless you annotate them appropriately.
Put the jax-rs in a CDI managed context by annotating it appropriately
#Path("/test/")
#javax.enterprise.context.RequestScoped
public class MyController {
#Inject
private MyService myService;
#GET
#Path("/foo/{count}")
#OAuthSecurity(scope = "login")
#Produces("application/json")
public Response news(#PathParam("count") int count) {
return Response
.ok(myService.getBar(count))
.build();
}
}
Also be sure that the annotation used for your service is
#javax.enterprise.context.RequestScoped
Based on the inputs provided by you please go through the below checklist.
Your services and controllers are in the same module and its packaging type is war, So you must place your beans.xml in this path src/main/resources/WEB-INF/beans.xml. (If this is Java EE 7 application then beans.xml is optional.
In your AccountApplication class try hardcoding the package name to ch.webapp.presentation
#Override
protected String getPackageToScan() {
return "ch.webapp.presentation";
}
This is just to check Behaviour of MFPJAXRSApplication.getPackageToScan() method whether it is scanning the specified package only or its child packages too.
Except these, everything seems fine to me. If this still doesn't work add complete application startup logs so that community can find the root cause of it.
This is classical mistake. CDI works for managed beans (for instance EJB's and servlets). If you want to enable it on your JAXRS bean, you have to make it "managed", that is annotate MyController as (for instance) javax.annotation.ManagedBean or as a javax.ejb.Stateless.
Also beware that in case of webapp (.war), the beans.xml file has to be located in the WEB-INF folder !

Websphere Application Server 9.0.0.1 - EntityManager is null every other request

I'm trying to run a project on WAS 9.0.0.1, that currently works fine on WAS 8.5.5.x. The problem seems to be that entitymanager is not being injected into the DAO, but this only happens every other request. So when doing the em.createNamedQuery in the DAO it is throwing a NullPointerException because the em is null, like I explained above the strange thing is that it is only failing like this every other request. Any ideas?
Persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="OperationsAPI" transaction-type="JTA">
<jta-data-source>jdbc/operations</jta-data-source>
<class>com.i3.operations.entities.Operation</class>
<properties>
<property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
</properties>
</persistence-unit>
</persistence>
Resource class:
#Path("/operations")
#Api("Operations API")
#Stateless
public class OperationsService {
public static Logger logger = Logger.getLogger(OperationsService.class.getName());
#Context
UriInfo uriInfo;
#EJB
private static OperationDAO operationDAO;
public OperationsService() {
operationDAO = new OperationDAO();
}
#GET
#ApiOperation(value = "Gets all operations", response = Operation.class, responseContainer = "List")
#Produces(MediaType.APPLICATION_JSON)
public Response getOperationsAll() {
List<Operation> operations = operationDAO.getOperationsAll();
return Response.ok().entity(operations).build();
}
}
DAO:
#Stateless
public class OperationDAO {
public static Logger logger = Logger.getLogger(OperationDAO.class.getName());
#PersistenceContext(unitName="OperationsAPI")
private EntityManager em;
public List<Operation> getOperationsAll() {
logger.info("EntityManager: " + em);
TypedQuery<Operation> query = em.createNamedQuery("Operation.findAll", Operation.class);
return query.getResultList();
}
}
You typically don't want to mix use of both the new operator and also dependency injection (CDI, etc.) to set the same object references in a given class.
If your dependency graph is mostly using dependency injection then dependency injection (DI) should be instantiating all the objects. Otherwise you end up with the case that you create an object instance that DI doesn't know about, so it doesn't know to inject its dependencies into.
This is probably what's happening in your case. Since these EJB instances are pooled, you may end up with some of your instances having been initialized correctly, and some not.
You probably want to change to just (or remove and default):
public OperationsService() {}
I'll mention I'm not sure injecting into a static field is a good idea, but I'm not really enough of an expert to suggest removing the static modifier from operationDAO.

Arquillian - programmatic configuration

I am writing integration tests using Arquillian with embedded glassfish 3.1.2.2 using TestNG. I want to be able to run those tests in parallel, and for this case i need to dynamically configure glassfish ports and database name (we already have this set-up, and I want to reuse it of arquillian tests). What I am missing is a 'before container start' hook, where I could prepare the database, lookup free ports and update my glassfish configuration (domain.xml, could also be glassfish-resources.xml). Is there a 'clean' solution for this, or my usecase was not foreseen by Arquillian developers?
The hacky way I solved it currently is to override arquillian's beforeSuite method but this one gets called twice - at test startup and then in the container (therefore my pathetic static flag). Secondly, this solution would not work for JUnit based tests as there's no way to intercept arquillian's before suite:
public class FullContainerIT extends Arquillian {
private static boolean dbInitialized;
//#RunAsClient <-supported by #Test only
#Override
#BeforeSuite(groups = "arquillian", inheritGroups = true)
public void arquillianBeforeSuite() throws Exception {
if (dbInitialized == false) {
initializeDb();
dbInitialized = true;
}
super.arquillianBeforeSuite();
}
}
Some ideas I had:
+ having #BeforeSuite #RunAsClient seems to be what I need, but #RunAsClient is supported for #Test only;
+ I have seen org.jboss.arquillian.container.spi.event.container.BeforeStart event in Arquillian JavaDocs, but I have no clue how to listen to Arquillian events;
+ I have seen there is a possibility to have #Deployment creating a ShrinkWrap Descriptor, but these do not support Glassfish resources.
I found a clean solution for my problem on JBoss forum. You can register a LoadableExtension SPI and modify the arquillian config (loaded from xml). This is where I can create a database and filter glassfish-resources.xml with proper values. The setup looks like this:
package com.example.extenstion;
public class AutoDiscoverInstanceExtension
implements org.jboss.arquillian.core.spi.LoadableExtension {
#Override
public void register(ExtensionBuilder builder) {
builder.observer(LoadContainerConfiguration.class);
}
}
package com.example.extenstion;
public class LoadContainerConfiguration {
public void registerInstance(#Observes ContainerRegistry, ServiceLoader serviceLoader) {
//Do the necessary setup here
String filteredFilename = doTheFiltering();
//Get the container defined in arquillian.xml and modify it
//"default" is the container's qualifier
Container definition = registry.getContainer("default");
definition.getContainerConfiguration()
.property("resourcesXml", filteredFilename);
}
}
You also need to configure the SPI Extension by creating a file
META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
with this contents:
com.example.extenstion.AutoDiscoverInstanceExtension

EJB Injection failure on deploy

I've got a problem exxh EJB's.
First of all, my setup: I am using GlassFish & JEE6. I have got a REST-Service packaged as a WAR and a bean packaged as an EJB-Jar. They are not inside an EAR.
The EJB should be used from the REST-WAR via #EJB, but when I try to deploy the WAR, GlassFish shows this error:
Error occurred during deployment:
Exception while deploying the app [exx-upload-1.0] : Cannot resolve reference Local ejb-ref name=com.ex.exx.model.FileUpload/ocr,Local 3.x interface =com.ex.exx.api.IOCRService,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session. Please see server.log for more details.
(The EJB was deployed before without any erros).
I have no clue why. Here is the EJB Code:
Interface:
#Local
public interface IOCRService {
public String performOCRonImage(BufferedImage input);
}
and Implementation:
#Stateless
#LocalBean
public class OCRScanner implements IOCRService {
private Logger logger = Logger.getLogger(this.getClass().getName());
private final static String NOT_RECOGNIZED = "Can not regocnize text";
/**
* Default constructor.
*/
public OCRScanner() {
logger.log(Level.INFO, "### OCR SCANNER BUILD" + this);
}
public String performOCRonImage(BufferedImage input) {
logger.log(Level.INFO, "### OCR SCANNER CALLED" + this);
}
...
And here is the important part in the WAR:
public class FileUpload {
private final File PROPERTIES_FILE = new File(
"fileUploadProperties.properties");
private final String PARAMETER_NAME = "file";
private final Logger logger = Logger.getLogger(this.getClass().getName());
#EJB
private IOCRService ocr;
public Response uploadFile(...) {
// do some stuff
logger.log(Level.INFO, "### EJB" + ocr.toString())
}
Anny suggestions? I can not find my failure here.
Solved this, by replaceing #Local with #Remote.
This works, however, I am not satisfied as I do not understand why.
Basically, given the specs (eg. explained in the tutorial), an application can only access other application's EJB, if they are decorated with #Remote.
Thus, you have 3 options:
decorate your EJB with #Remote (what you have done),
package both together inside an ear (as they would reside in the
same application then). But if you intent to deploy them in seperate
applications or even seperate servers, use 1.)
use CDI with #Inject, but this will still only discover the EJB if
either in the same application, or decorated as #Remote if not.
HTH,
Alex
You should not use #EJB if the target is not an EJB. I guess this is your case because you are trying to inject into a class in your WAR.
Instead use:
#Inject
private IOCRService ocr;
Basically, #Inject is better in most cases, because:
it is more typesafe,
it supports #Alternatives
it is aware of the scope of the injected object.
Another solution it's to add #Stateless(name=""), this worked form