In our quarkus app we use a LDAP server to retrieve user data. The code in a nutshell looks like this:
Properties env = new Properties();
env.put("com.sun.jndi.ldap.read.timeout", "5000");
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=" + ldapUser + "," + ldapOrganization);
env.put(Context.SECURITY_CREDENTIALS, ldapPw);
env.put(Context.PROVIDER_URL, ldapServer);
new InitialLdapContext(env, null);
With the jre version it all runs well, but with quarkus native I get ClassNotFoundExceptions. Build and startup are successful, but calling the app doesn't work.
At first I got a
java.lang.ClassNotFoundException: com.sun.jndi.ldap.LdapCtxFactory
but I could get rid of it by including the quarkus-elytron-security-ldap extension and disabling it by quarkus.security.ldap.enabled=false.
Now the exception is
java.lang.ClassNotFoundException: javax.net.ssl.SSLSocketFactory. I wonder how the quarkus-elytron-security-ldap extension talks to the ldap server without that error.
I'm using quarkus 1.13.7.Final, mvn 3.6.3 and azul jdk 11.0.10 on ubuntu 20.04.
What I discovered so far:
I did include a truststore as explained in https://quarkus.io/guides/native-and-ssl#the-truststore-path and other https calls to rest servers do work with it.
The solution from Quarkus LDAP get user data would work on my machine, but it needs to work for developers on win machines as well.
https://github.com/oracle/graal/issues/2808 sounds like SSLSocketFactory is and will not be part of GraalVM, but then how does the quarkus-elytron-security-ldap extension talk to the ldap server?
Ran into the same problem today.
Seems that JNDI isnt active by default.
Use this setting
quarkus.naming.enable-jndi=true
to enable JNDI in Quarkus apps.
Related
Context: Existing JavaSE application written in Swing which fires up an embedded server (so far it was Jetty) but we need to switch to Java EE, so we thought about bringing in an enterprise container (candidates are: Payara, Tomee, Wildfly).
The server should be able to run a web app based on dynamic input: web context, with its own web.xml, specific web resources which are not known at build time, so uber jar is not really an option for us.
We have successfully started a web app on Payara using code like the following (this is not working code, but it shows the steps we took for using Payara)
GlassFish glassfish;
WebContainer container;
GlassFishRuntime glassfishRuntime = = GlassFishRuntime.bootstrap();
glassfish = glassfishRuntime.newGlassFish();
glassfish.start();
// Access WebContainer
container = glassfish.getService(WebContainer.class);
WebContainerConfig config = new WebContainerConfig();
container.setConfiguration(config);
Context context = container.createContext(contextPathLocation);
m_webAppContexts.put(p_contextName, context);
WebListener listener = container.createWebListener("listener-1", HttpListener.class);
listener.setPort(myDynamicPortNumber);
container.addWebListener(listener);
container.addContext(context, myDynamicContextPath);
context.addServlet(myDynamicMapping, myServletName);
This is all working and a basic web application starts in Payara when invoked from our Java SE application.
We also have a fragment of web.xml declaring additional servlets that we want to bring in this dynamic deployment if given conditions are satisfied.
What is the best way to override the existing web.xml with fragments from another web.xml? We need pointers to documentation, directions from more experienced Payara users.
This is not possible with Payara or Wildfly, as they work very differently from how Jetty works.
However, it is possible with Tomee.
We recently migrated to Spring boot 1.3.1 from the traditional spring project.
Our existing clients use Tyrus 1.12 as a websocket client.
After the upgrade, we found that the clients no longer connect and throws AuthenticationException. Strangely, they are able to connect for the first time since server restart and soon after throws AuthenticationException.
Digging a bit more, I found that Tyrus receives a 401 initially and passes on credentials subsequently. The server logs indicate the same behaviour, by first assigning ROLE_ANONYMOUS and then the correct role, ROLE_GUEST there after.
It seems like after the negotiation, the server closes connection and disconnects.
I observed the same behaviour when using spring stomp websocket client with Tyrus.
ClientManager container = ClientManager.createClient();
container.getProperties().put("org.glassfish.tyrus.client.sharedContainer", true);
container.getProperties().put(ClientProperties.CREDENTIALS, new Credentials("guest", "guest"));
StandardWebSocketClient webSocketClient = new StandardWebSocketClient(container);
final CountDownLatch messageLatch = new CountDownLatch(10);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
This same server setup works fine when the credentials are sent in the header.
stompClient.connect(url, getHandshakeHeaders("guest", "guest"), handler);
And this will NOT work since the credentials are not in the header
ListenableFuture<StompSession>session = stompClient.connect(url, handler, "localhost", "8080");
I am not understanding why it is working one way and not the other.
After upgrading to spring-boot, our software is no longer backwards compatible and will have to ask all our external clients to inject the authorization in the header before receiving a 401.
Can someone please help?
My earlier post with stacktrace
We want to migrate an old application from Glassfish to TomEE. We encounter a problem about JNDI.
When I run the cmd for Glassfish server asadmin list-jndi-entries I get some JNDI entries:
java:global: com.sun.enterprise.naming.impl.TransientContext
UserTransaction: com.sun.enterprise.transaction.TransactionNamingProxy$UserTransactionProxy
com: com.sun.enterprise.naming.impl.TransientContext
OURAPPSERVER-Q2: com.ourcompany.product.OurAppServer
com.sun.enterprise.container.common.spi.util.InjectionManager: com.sun.enterprise.container.common.impl.util.InjectionManagerImpl
ejb: com.sun.enterprise.naming.impl.TransientContext
jdbc: com.sun.enterprise.naming.impl.TransientContext
AppServer: com.sun.enterprise.naming.impl.TransientContext
As you can see, there is AppServer JNDI entry. This entry is bind from our code manually.
try {
InitialContext context = new InitialContext();
context.rebind("AppServer/facede", this);
} catch (NamingException e) {
e.printStackTrace();
logger.severe("Unable to register the service facade bean, "
+ "JPOS will not be able to access services");
}
This code is not working in TomEE. I get some error like:
javax.naming.NameNotFoundException: Name [AppServer/facede] is not bound in this Context. Unable to find [AppServer].
at org.apache.naming.NamingContext.bind(NamingContext.java:899)
at org.apache.naming.NamingContext.rebind(NamingContext.java:225)
It seems like the container can't found context base on AppServer.
I am not a master of JNDI. Then I have checked some documents. The java:comp/env/ is the basic namespace. And "jdbc" for DBCTM DataSource references, "jms" for JMS connection factories, "mail" for JavaMail connection factories, "url" for URL connection factories.
We don't want to change too much on our old application code. It's not use any special features of Glassfish. I want to know how to define a JNDI in a correct way.
Is there anyone could tell me why Glassfish can use AppServer as namespace, but TomEE can't.
Tomcat (then TomEE) is not designed to change JNDI at runtime like it. Saying it simply the best is to not use this pattern but a contextual resource. Inject the resource you desire and that's this resource you change instead of JNDI (which is quite more impacting that it seems)
I am porting a suite of related applications from WebLogic to JBoss EAP v6.2.
I have set up a data source connection using the JBoss command line interface and hooked it to an oracle database. This database has a name of "mydatasource" and a JNDI name of
"java:jboss/datasources/mydatasource" as per JBoss standards. I can test and validate this database connection.
However, when I try to port the code and run it, the connection doesn't work. The code that worked in WebLogic was simply:
InitialContext ic = new InitialContext() ;
DataSource ds = (DataSource)ic.lookup(dataSource) ;
with a value in dataSource of "mydatasource".
This worked in Web Logic but in JBoss it throws a NameNotFoundException
javax.naming.NameNotFoundException: mydatasource-- service jboss.naming.context.java.mydatasource
Clearly there is a difference in how the InitialContext is set up between the two servers.
But this port involves a large number of small applications, all of which connect to the datasource via code like that above. I don't want to rewrite all that code.
Is there a way through configuration (InitialContextFactory, maybe) to define the initial context such that code like that above will work without rewriting, or perhaps is there another way of naming the datasource that JBoss will accept that would allow code like that above to work without rewriting?
Or must we bite the bullet and accept that this code needs a rewrite?
Update: Yes, I know that simply passing "java:jboss/datasources/mydatasource" to the InitialContext lookup solves the problem, but I am looking for a solution via configuration, rather than via coding if there is such a solution.
The way to do this correctly through configuration is to use
java:comp/env/jdbc/myDataSource
then use resource-ref in web.xml to map it to the declare datasource and use weblogic.xml or jboss-web.xml to actually map it to the real one
in weblogic admin console, when you define datasource it can be jdbc/realDataSource
JNDI path Tomcat vs. Jboss
For weblogic http://docs.oracle.com/cd/E13222_01/wls/docs103/jdbc_admin/packagedjdbc.html
I am using scribe 1.3.0 for OATH authentication. This is on Tomcat 7 under Ubuntu.
I am pretty sure this is some sort of a pilot error but cannot figure out what is wrong exactly...
I create the service and token in the constructor of my client class:
public Client()
{
m_service = new ServiceBuilder()
.provider(Api.class)
.apiKey(CONSUMER_KEY)
.apiSecret(CONSUMER_SECRET)
.debug()
.build();
m_accessToken = new Token(OAUTH_TOKEN, OAUTH_TOKEN_SECRET);
}
Later on when time comes to make a request I use the service in a function:
OAuthRequest request = new OAuthRequest(Verb.GET,
url);
m_service.signRequest(m_accessToken, request);
Since I added the debug() tag to the ServiceBuilder I get the following output:
signing request: URL
setting token to: Token[xxxx , xxxxx]
generating signature...
thats it.. nothing else happens, the code just seems to die there.
I tried to catch Exception from the m_service call but it does not throw exception.
I had tried this code before on a different Windows machine with Jetty and it worked but I dont have access to that machine or OS anymore..
What could I be doing wrong? Is there anything else I can do to get more debug output?
-Wish
Turns out that I needed to include the apache codec jar files in Tomcat.
I did go back to try my app on Jetty again under Windows, that worked without the codec. I am not entirely sure why linux+Tomcat needs apache codec while Jetty+Windows7 does not..
If I had Maven would not have this issue..