Dozer DozerBeanMapper Instantiation Startup EJB App Server Glassfish - glassfish

Dozer's documentation states that you should only have one instance of DozerBeanMapper running in the app on the server. For initial development I ignored this, now I want to update the app to do this.
How can I instantiate the DozerBeanMapper class when the application starts on glassfish, and how would I access its "map" method in another class once the application has started or been newly deployed?
This is for EJBs so I can't use any servlet to do this.
OK, so I've finally had time to refactor this code. With the pointer from #Mikko Maunu, I am editing my question to provide the code that I have working for me for anyone who might find it useful in the future.
package com.xyz.utilities.singleton;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import org.dozer.DozerBeanMapper;
#Startup
#Singleton
public class DozerInstantiator {
private DozerBeanMapper mapper = null;
#PostConstruct
void init() {
mapper = new DozerBeanMapper();
}
public DozerBeanMapper getMapper() {
return mapper;
}
}
And here is a straight forward usecase:
Inject an EJB member variable to your client class:
#EJB
DozerInstantiator di;
Within a method somewhere in the client class you can invoke the dozer mapper like so:
Credentials credentials = di.getMapper().map(credentialsDTO, Credentials.class);
// or
Credentials credentials = new Credentials();
di.getMapper().map(credentialsDTO, credentials);
If this is wrong or off base, someone please leave a comment. Until then, this seems to work so I'll use this solution I've developed with Mikko's input.

If you are using GlassFish 3.x, then you can use EJB 3.1 Singleton Session Bean:
#Startup //initialization in application startup
#Singleton //only one instance
public class DozerInitializer {
private String status;
#PostConstruct //executed once and only once when sole instance is created
void init {
//do steps needed to instantiate DozerBeanMapper
//here
}
}

Related

Is it possible to add an instance of singleton framework to CDI context?

I'm trying to integrate StarMX framework (https://github.com/rogeriogentil/starmx) into a legacy web application. This framework uses JMX techonology and is initialized using the Singleton pattern: StarMXFramework.createInstance(). The web application uses Java EE 6 technologies such as EJB and CDI (also DeltaSpike). However, the way the framework is being initialized (code below) doesn't add its instance to the CDI context.
import org.starmx.StarMXException;
import org.starmx.StarMXFramework;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
#Startup
#Singleton
public class StarMXSingleton {
private StarMXFramework starMX;
#PostConstruct
public void postConstruct() {
try {
starMX = StarMXFramework.createInstance();
} catch (StarMXException e) {
(...)
}
}
#PreDestroy
public void preDestroy() {
if (starMX != null) {
try {
starMX.shutdown();
} catch (StarMXException e) {
(...)
}
}
}
}
I know that is possible to extend CDI, but is it possible to add an instance of singleton framework to CDI context?
There are two ways, first and easy one is a producer. Here is a link to what CDI producers are and how they work. In short, CDI will use this producer to create the instance of a bean whose types are mandated by the return type of the producer method.
The producer method has to be placed inside a CDI bean so that is it picked up by CDI. Note that the scope of the producer affects how often it will be invoked, just as it would be with standard bean. Here is how it could look like:
#ApplicationScoped
public class SomeCdiBeanInYourApplication {
#Produces //denotes producer method
#ApplicationScoped // scope of produced bean, use CDI scope (the singleton you have is EJB annotation)
public StarMXFramework produceMxFramework() {
return StarMXFramework.createInstance();
}
}
Second means is then CDI extension, namely a lifecycle observer for AfterBeanDiscovery event where you can addBean(). Here is a link to CDI 2.0 spec, feel free to browse older versions based on what version you are on.
I won't write code for that as it is rather complex and long, the producer should do the trick for you.
See also
Please explain the #Produces annotation in CDI

start application (from jar) on Weblogic startup

I'm using Weblogic 12c, I need to run app before/with the web app starts.
the app should fetch information and write it to db.
I read that in previous versions of WL programmers used to work with ApplicationLifecycleListener, but it is deprecated now.
I'm compiling the project to ear file.
I also tried to use ejb3.2 eager singleton, but it didn't worked.
Is there any working alternative?
I solved the issue by creating EJB as the following:
#Singleton
#Startup
public class StartupBean {
#PostConstruct
private void startup() { ... }
#PreDestroy
private void shutdown() { ... }
...
}
Creating the EJB Singleton instances is one of the Weblogic life cycle init calls, I put my java code under startup() method.

Inject EJB into JAX-RS 2.0 subresource when subresource is got via ResourceContext

I am using Jersey 2.8 with Glassfish 4.0.
I have a resource locator class which looks like below
#Path("/")
#ManagedBean
public class MyServiceLocator {
#Context
ResourceContext rc;//javax.ws.rs.container.ResourceContext
#EJB
private MyEJBHome myEJB;
#Inject//javax.inject.Inject
MySubService mss;
#Path("/mysubservice")
public MySubService getMySubService() {
return rc.getResource(MySubService.class);
//also tried return rc.initResource(new MySubService());
}
}
and a sub resource class which is
#ManagedBean
public class MySubService {
#EJB
public MyEJBHome myEJB;
#Context
HttpHeaders heads;
/*#Inject
private myEJBHome myEJB2;*/
#Path("/mypath")
#GET
#Produces(MediaType.APPLICATION_JSON)
public Object doSomething(#Context SecurityContext securityContext) {...}
}
beans.xml file is put to META-INF and WEB-INF.
In MyServiceLocator class private MyEJBHome myEJB is injected successfully. And MySubService mss object is injected successfully and with EJB injected into it.
The problem is that when MySubService is got via ResourceContext the EJB is not injected into it.
Previously i used Glassfish 3 and Jersey 1.17 with proprietary ResourceContext and absolutely the same code worked ok.
I googled a lot and read a lot of similar (but a bit different) questions and as i understood non JAX-RS stuff (EJB in my case) can't be injected when sub resource is got via ResorceContext. Is it true? If yes how can i work it around?
The one possible solution is to inject sub resource objects to the resource locator class but there are too many of them and it seems to be very ugly.
EDIT Injection with #Inject works if to create a binder, bind ejb class to ejb interface and register that binder. But i don't want to describe binding for hundreds of my ejbs. Also as i understand it is specific binding fir HK2 system and i don't want to be linked to it.
Different actions with setting #Named annotations and trying to inject via CDI didn't help. It seems that when getting sub-resource via ResourceContext Jersey uses only HK2 and that's why CDI can't do it's work. Is that correct?
The only appropriate solution i found was to create my own annotation and inject provider.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface EJBInject {
String beanName();
}
#Provider
public class EjbInjectProvider implements InjectionResolver<EJBInject> {
#Override
public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
try {
String beanName = injectee.getParent().getAnnotation(EJBInject.class).beanName();
return new InitialContext().lookup("java:global/MyApp/" + beanName);
} catch (Exception e) {
return null;
}
}
#Override
public boolean isConstructorParameterIndicator() {
return false;
}
#Override
public boolean isMethodParameterIndicator() {
return false;
}
}
Then ejb can be injected using that annotation like
#EJBInject(beanName="MyBean")
MyBeanEJBHome myBean;
In such case any standard EJB injections which MyBeanEJBHome might need work correctly, too.

NullPointerException and #EJB

I use EJB3+JavaEE6+JBoss. I am absolutely newbie in EJB. I wrote this code:
package server.ejb;
#Remote
public interface HelloUser
{
void sayHello( String name );
}
#Stateless
public class HelloUserBean implements HelloUser
{
#Override public void sayHello( String name )
{
System.out.println( "Hello " + name );
}
}
Having assebled this code with Maven and deployed it on JBoss, I wrote a client:
import server.ejb.HelloUserBean;
import javax.ejb.EJB;
public class Test
{
#EJB
public static HelloUserBean bean;
public static void main( String... args )
{
bean.sayHello( "Alex" );
}
}
After compiling, I've got NullPointerException. It said that bean was null. Using JDNI + PersistentContext I could get a success, but I still can't use DI as well. Please, help me
I reorginized my code! Actually I wrote another server-side project with the same sence and a standalone client-app. Here is the structure of server-side app:
#Remote
public interface EchoRemote{
String getMessage();
}
#Stateless
public class EchoBean implements EchoRemote{
#Override
public String getMessage(){
return "Hello From Stateless Bean";
}
}
public class InvokationClient{
#EJB
private EchoRemote bean;
public String getMessage(){
return bean.getMessage();
}
}
And here is the client-side standalone app:
import com.steeplesoft.client.InvokationClient;
public class Main{
public static void main( String... args ) throws IOException{
InvokationClient client = new InvokationClient();
FileWriter fileWriter = new FileWriter( "D:/invokation_client_test.txt" );
fileWriter.write( client.getMessage() );
fileWriter.close();
}
}
I've got empty file and NullPointerEception in console
I hope you can help me :) It's tremendously important for me!!!
So you start your Test-class standalone in a separate JVM. Where did you configure to which JBoss it should connect? Which component does the dependency injection? Since you don't have a DI container that manages the Test-class and since the connection to JBoss is not configured anywhere, this can't work.
In order to make it work, you can do the following:
1) Write a Servlet, use #EJB in the Servlet and deploy it on JBoss. Put your EJB and the Servlet in the same WAR to make it easy. The Servlet is managed by the container and DI works. As a newbie with EJB I would do this first.
2) Do a JNDI-Lookup and call your EJB from a standalone client as described in https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
3) Use an Application Client Container (ACC) as described in http://blogs.steeplesoft.com/posts/2011/02/22/java-ees-buried-treasure-the-application-client-container/ Deploy the EAR to jboss and invoke the client locally
$JBOSS_HOME/bin/appclient.sh --host remote://localhost:4447 ./local/path/to/enterpriseapplication-0.1-SNAPSHOT.ear#appclient-0.1-SNAPSHOT.jar
Remark: When I tried the example from blogs.steeplesoft.com, I had problems with the Swing classes, but it did work JBoss EAP 6.2, when I removed the Swing classes.

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