How to conduct a lookup of an EJB from a servlet context? - servlets

I have a POJO that was instantiated from a servlet. I need to make a lookup of an EJB within this POJO, either CDI or JNDI. My JEE container is TomEE 1.6.0.
My question is this: need the EJB have remote interface? Because if I instantiate it directly from the servlet by #EJB the remote interface does not need...
Just see this simple example which always throws NameNotFoundException.
#Stateless
public class MyEJB
{
public String sayHello()
{
return "Hello";
}
}
The next servlet try yo lookup MyEJB:
#WebServlet("/myServlet")
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID=1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException
{
try
{
Context ctx = new InitialContext();
MyEJB ejb = (MyEJB) ctx.lookup("MyEJB");
System.out.println(ejb.sayHello());
}
catch(Exception ex)
{
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
The line: MyEJB ejb = (MyEJB) ctx.lookup("MyEJB"); always throws NameNotFoundException. But if I use #EJB it work fine. But I need do the lookup in JNDI mode because finally I will instantiate this EJB within a POJO.
So, why fails this lookup ?

This has nothing to do with remote interfaces.
When you declare MyEJB in servlet using #EJB it works, because servlet is container-managed - your TomEE server instantiates servlet object. However declaration of MyEJB in MyPojo (also using #EJB) won't work, because MyPojo is not container-managed - it is created using new MyPojo(), not by TomEE server.
You could for example make MyPojo another EJB (using #Stateless) and inject it using #EJB to the servlet - not by creating new MyPojo().

I can solve this problem by myself by instrospecting the JNDI tree with this simple class:
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
public class JndiInstrospector
{
public static void print()
{
try
{
Context ctx = new InitialContext();
String n = ctx.getNameInNamespace();
_print(n);
}
catch(Exception ex)
{
ex.printStackTrace();
throw new RuntimeException();
}
}
private static void _print(String name) throws Exception
{
try
{
System.out.println("Name in manespace: "+name);
Context ctx = new InitialContext();
NamingEnumeration<Binding> list = ctx.listBindings(name);
while( list.hasMoreElements() )
{
Binding b = list.nextElement();
String s = b.getName();
_print(name+"/"+s);
}
}
catch(Exception ex)
{
// ignore
}
}
}
Finally, the EJB That I was espected to lookup was found at:
"java:/openejb/local/FacadeBeanLocalBean", where FacadadeBean is the name of my EJB (stateless session bean).

Related

CDI Injection and #Model Annotation

I have two questions regarding two annotations:
1) Why does the "faceContext" has to be injected from Resources class? Instead, MemberController can directly use "FacesContext.getCurrentInstance()" in register() method to obatin a FacesContext object? It seems much simpler to do that.
2) Can #Model be replaced by #Singleton? Or even #ApplicationScoped?
Thanks.
MemberController.java
#Model
public class MemberController {
#Inject
private FacesContext facesContext;
#Inject
private MemberRegistration memberRegistration;
#Produces
#Named
private Member newMember;
#PostConstruct
public void initNewMember() {
newMember = new Member();
}
public void register() throws Exception {
try {
memberRegistration.register(newMember);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Registered!", "Registration successful");
facesContext.addMessage(null, m);
initNewMember();
} catch (Exception e) {
String errorMessage = getRootErrorMessage(e);
FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Registration unsuccessful");
facesContext.addMessage(null, m);
}
}
}
Resources.java
public class Resources {
// use #SuppressWarnings to tell IDE to ignore warnings about field not being referenced directly
#SuppressWarnings("unused")
#Produces
#PersistenceContext
private EntityManager em;
#Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
#Produces
#RequestScoped
public FacesContext produceFacesContext() {
return FacesContext.getCurrentInstance();
}
}
injecting the FacesContext istead of getting it using the static factory method has the advantage that you will only once have to care about how to get the current context, when implementing the producer method or field. Each time you need the context you can simply inject it and it is fully transparent to you where it comes from. This might also have some benefits when anything changes in how to get the context, ...
The answer to the second question depends on your requirements. Since #Model is simply a stereotype for #RequestScoped and #Named, you cannot directly replace it with #Singleton or #ApplicationScoped since these both annotations adwise the container to create a single object for all requests. Nevertheless, if this meets your requirements better than having a different object for each request, you are free to change it ;)

EJB with JNDI not listed in the glassfish JNDI list

I have made an EJB with JNDI, using the annotations.
I made a jar of that EJB code and deployed it in the GlassFish server (version 3).
I am able to get the object of the EJB in a remote client application, using the JNDI lookup.
But I am not able to get the EJB name or the mappedName in the GlassFish JNDI list.
I use the command asadmin list-jndi-entries to get the list of JNDI entries.
#Remote
public interface TestEjbJndi {
public Object test();
}
#Stateless(name="TestSdkInterface", mappedName="/test/ejb/jndi")
public class TestEjbJndiImpl implements TestEjbJndi{
#Override
public Object test(){
System.out.println("Inside getProtocolData");
return null;
}
}
public class RemoteClient {
public static void main(String[] args) {
try {
Context ctx = new InitialContext();
lookup(ctx);
} catch (NamingException ne) {
ne.printStackTrace();
}
}
private static void lookup(Context ctx) throws NamingException {
System.out.println("Inside lookup");
try{
Object object = ctx.lookup("/test/ejb/jndi");
System.out.println("lookup done, object :"+object);
TestEjbJndiImpl teji= (TestEjbJndiImpl)object;
teji.test();
}catch(NamingException ne){
ne.printStackTrace();
}
}
}

How to setup OAuth2RestTemplate (Post Updated)

I am not sure if I have OAuth2RestTemplate configured correctly. I am getting the following error when I run the tester class.
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#1df3248: defining beans [propertyConfigurer,dataSource,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,emf,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,accountRepository,questionRepository,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor#0,jpaQuestionService,jpaAccountService,passwordEncoder,accountHelper,tradeConfig,org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#1,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,baseOAuth2ProtectedResourceDetails,oAuth2ProtectedResourceDetails,accessTokenRequest,oAuth2ClientContext,oAuth2RestTemplate]; root of factory hierarchy
Exception in thread "main" error="access_denied", error_description="Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it."
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:216)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:168)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:89)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:442)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:123)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:385)
at com..main(Tester.java:44)
Classes
#Configuration
public class AppConfig {
#Bean
//#Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES)
public BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails(){
BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails = new BaseOAuth2ProtectedResourceDetails();
baseOAuth2ProtectedResourceDetails.setClientId(clientId);
baseOAuth2ProtectedResourceDetails.setClientSecret(clientSecret);
return baseOAuth2ProtectedResourceDetails;
}
#Bean
public DefaultAccessTokenRequest accessTokenRequest(){
return new DefaultAccessTokenRequest();
}
#Bean
public OAuth2ClientContext oAuth2ClientContext(){
return new DefaultOAuth2ClientContext(accessTokenRequest());
}
#Bean
public OAuth2RestTemplate oAuth2RestTemplate(){
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(baseOAuth2ProtectedResourceDetails(),oAuth2ClientContext());
return restTemplate;
}
}
Tester Class
public class Tester {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath*:jpa-app-context.xml");
ctx.refresh();
EntityManagerFactory emf = (EntityManagerFactory) ctx.getBean("emf");
EntityManager em = emf.createEntityManager();
TransactionSynchronizationManager.bindResource(emf , new EntityManagerHolder(em));
OAuth2RestTemplate oAuth2RestTemplate = (OAuth2RestTemplate) ctx.getBean("oAuth2RestTemplate");
//OAuth2RestTemplate oAuth2RestTemplate = ctx.getBean(OAuth2RestTemplate.class);
String uri="https:api..";
Object obj = oAuth2RestTemplate.exchange(uri, HttpMethod.POST, null, Object.class);
System.out.println("Tester Object: "+ obj.toString());
}
}
I faced the same exception, but with another protected resource type.
Generally, the exception raises only when AccessTokenProviderChain can't find an appropriate *AccessTokenProvider for particular *ProtectedResourceDetails instance. Meaning, when you try to do the following:
ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri(url);
resource.setClientId(clientId);
resource.setClientSecret(secret);
resource.setGrantType("password");
return resource;
The code expects a client_credentials grant type since we use a ClientCredentialsResourceDetails, but we pass password value.
Here the code that worked in my case:
private OAuth2ProtectedResourceDetails withOAuth2Authentication(final String url, final String clientId, final String secret) {
ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
resource.setAccessTokenUri(url);
resource.setClientId(clientId);
resource.setClientSecret(secret);
// here you can provide additional properties such as scope etc.
return resource;
}
#Bean
RestTemplate callbackClientV2() {
AccessTokenRequest atr = new DefaultAccessTokenRequest();
return new OAuth2RestTemplate(
withOAuth2Authentication(v2ServerUrl, v2Username, v2Password),
new DefaultOAuth2ClientContext(atr)
);
}

How can I write custom servlet context init method

I wish to set up a few application wide variables with servletContext.setAttributes on servlet context initialization phase .How can I achieve this.
Implement javax.servlet.SevletContextListener which gets a callback when javax.servlet.ServletContext is initialized.
Here is the example:
public class MyServletContextListener implements ServletContextListener
{
public void contextInitialized(ServletContextEvent sce)
{
ServletContext sc = sce.getServletContext();
//do your initialization here.
sc.setAttribute(.....);
}
public void contextDestroyed(ServletContextEvent sce)
{
ServletContext sc = sce.getServletContext();
//do your cleanup here
}
}
If you would like to tie your logic closer to the servlet (and not use a listener), you can override the servlets init method. Like so:
#Override
public void init() throws ServletException {
ServletContext sc = getServletContext();
// Store our attribute(s)!
// Check first to make sure it hasn't already been set by another Servlet instance.
if (sc.getAttribute("key") == null)
sc.setAttribute("key", "value");
}
And you don't have to call through to super.init(config). See docs.

Servlet 3.0 support in embedded Jetty 8.0

For my unit-tests I use a simple test-server based on Jetty:
package eu.kostia.textanalysis.webservices.jetty;
import java.awt.Desktop;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class TestServer {
static private final String CONTEXT_PATH = "/webservice";
static private final String PROJECT_HOME = System.getenv("MY_WORKSPACE_HOME") + "/WebServices";
static public final int PORT = 8080;
private Server server;
private Exception startException;
private static class SingletonHolder {
private static final TestServer INSTANCE = new TestServer();
}
/**
* Returns the singleton instance of the test server.
*
* #return the singleton instance of the test server.
*/
public static TestServer getInstance() {
return SingletonHolder.INSTANCE;
}
private TestServer() {
server = new Server(PORT);
WebAppContext context = new WebAppContext();
context.setDescriptor(PROJECT_HOME + "/web/WEB-INF/web.xml");
context.setResourceBase(PROJECT_HOME + "/web");
context.setContextPath(CONTEXT_PATH);
context.setParentLoaderPriority(true);
server.setHandler(context);
}
/**
* Start the test server. This method returns only when the server is
* complete started. There is no effect when you invoke this method and the
* server is already running.
*/
public void start() {
if (!server.isRunning()) {
startException = null;
new Thread("TestServer") {
public void run() {
try {
server.start();
server.join();
} catch (Exception exc) {
startException = exc;
}
}
}.start();
while (true) {
if (startException != null) {
throw new Error(startException);
}
// Block this method call until the server is started
if (server.isStarted()) {
return;
}
}
}
}
/**
* Stop the test server.
*/
public void stop() {
try {
if (server.isRunning()) {
server.stop();
}
} catch (Exception e) {
throw new Error(e);
}
}
/**
* Returns {#code true} is the server is running.
*
* #return {#code true} is the server is running.
*/
public boolean isRunning() {
return server.isRunning();
}
public static void main(String[] args) throws Exception {
TestServer.getInstance().start();
Desktop.getDesktop().browse(new URI("http://localhost:8080/webservice/"));
}
}
It works very well for servlet configured in web.xml but I'd now like to use the new annotation syntax introduced by the Servlet Specification 3.0, for example:
#WebServlet(urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.print("<h1>HttpServlet using Servlet 3.0</h1>");
}
}
How shoud I configure Jetty in my TestServer class to process also annotation-based servlets?
Add to your code
context.setConfigurations(new Configuration[] {
new AnnotationConfiguration(), new WebXmlConfiguration(),
new WebInfConfiguration(), new TagLibConfiguration(),
new PlusConfiguration(), new MetaInfConfiguration(),
new FragmentConfiguration(), new EnvConfiguration() });
You only need to set the AnnotationConfiguration to get the auto-discovery of annotated classes to work. The rest of the configurations are so you can enable other aspects of the container. Supposedly you should be able to do this from the commandline, using OPTIONS=annotations,jsp,(etc...), but I never got that working. At least this way it should pick up your annotated classes properly in the embedded environment.
Also as a side note it appears the Eclipse jetty project has annotation turned off by default, whereas riptide claims to have them turned on by default. I'm guessing this is a difference in the configuration files.
Answering yet another year later.
In the current version of Jetty (8.1) you can accomplish exactly what you want with the command line:
java -jar start.jar OPTIONS=annotations,plus etc/jetty-plus.xml
invoked from the jetty home directory.
Jetty 8 is implementing the servlet 3.0 specification but it's still experimental.
You could also use the embedded glassfish 3 plugin to run your tests. See the below links for some info:
http://wikis.sun.com/display/GlassFish/3.1EmbeddedOnePager
http://ocpsoft.com/java/using-embedded-glassfish-with-maven/
http://embedded-glassfish.java.net/
I realise as I write this that there are no authoritative resource for using the Glassfish plugin in the manner Jetty is often used. However it does work in a similar way.
I hope this helps at least a bit.

Resources