I have EJB deployed on a WildFly 18 server. I want to send message to a queue deployed on a remote WildFly 18 server (through ActiveMQ Artemis). Is that possible using injection and JCA and a poole-connection-factory?
Connection factory and queue are configured in the remote Wildfly as below:
<subsystem xmlns="urn:jboss:domain:messaging-activemq:8.0">
...
<pooled-connection-factory name="remote-artemis" entries="java:/jms/remoteCF" connectors="remote-http-connector"/>
...
</subsystem>
On the remote server, the queue is configured as below:
<subsystem xmlns="urn:jboss:domain:messaging-activemq:8.0">
...
<jms-queue name="WildFlyCookbookQueue" entries="java:/jms/queue/test java:jboss/exported/jms/queue/test"/>
...
</subsystem>
UPDATE
Here is my EJB trying to send message to the remote Artermis (inside remote wildfly):
#Stateless
public class MessageSender {
#Inject
#JMSConnectionFactory("java:/jms/remoteCF")
#JMSPasswordCredential(userName = "jmsuser", password = "jmsuser2020")
private JMSContext context;
#Resource(lookup = "java:/jms/queue/test")
private Queue queue;
public void sendMessage(String message) {
context.createProducer().send(queue, message);
}
}
When I try to deploy the war containing this EJB, I get the error saying that the queue does not exist.
Thank you
Yes. It is possible to inject a JCA-based pooled-connection-factory into your EJB running on WildFly 18 and send a JMS message to a remote WildFly server.
Related
I have a WebApp JSP project deployed on Weblogic 12 as a WAR.
My gradle build includes mvc and webflux:
implementation 'org.springframework.boot:spring-boot-starter-web:2.3.2.RELEASE'
implementation ("org.springframework.boot:spring-boot-starter-security:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-oauth2-client:2.3.2.RELEASE")
implementation ("org.springframework.boot:spring-boot-starter-webflux:2.3.2.RELEASE")
I am trying to configure OAuth2 to use client_credentials flow from my client JSP application.
I need the #Controller class to use WebClient and propagate the access token to a Resource Server.
My Bean to create the WebClient is seen below.
#Bean
public ReactiveClientRegistrationRepository getRegistration() {
ClientRegistration registration = ClientRegistration
.withRegistrationId("ei-gateway")
.tokenUri("https://xxxxx.xxxxxxx.net/auth/oauth/v2/token")
.clientId("xxx-xxxx-43e9-a407-xxxxx")
.clientSecret("xxxxxx-3d21-4905-b6e5-xxxxxxxxxx")
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
return new InMemoryReactiveClientRegistrationRepository(registration);
}
#Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
return WebClient.builder()
.filter(oauth)
.defaultHeader("accept", "application/json")
.defaultHeader("content-type", "application/json")
.defaultHeader("environment", environment)
.filter(logRequest())
.filter(logResponse())
.build();
}
However I get the following error during compile:
Could not autowire. There is more than one bean of 'ReactiveClientRegistrationRepository' type.
Beans:
clientRegistrationRepository (ReactiveOAuth2ClientConfigurations.class)
getRegistration (WebSecurityConfiguration.java)
However when I uncomment out the getRegistration Bean method and configure the oauth client registration via the web.xml, then when deploying the application I get this error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}:org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I see from the ReactiveOAuth2ClientAutoConfiguration source code that the Reactive OAuth2 Auto Configuration is not run when ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition is set.
#Configuration(proxyBeanMethods = false)
#AutoConfigureBefore(ReactiveSecurityAutoConfiguration.class)
#EnableConfigurationProperties(OAuth2ClientProperties.class)
#Conditional(ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.class)
#ConditionalOnClass({ Flux.class, EnableWebFluxSecurity.class, ClientRegistration.class })
#Import({ ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration.class,
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration.class })
public class ReactiveOAuth2ClientAutoConfiguration {
}
Can anyone suggest a course of action? Is is possible to manually configure the ReactiveOAuth2ClientConfiguration?
Thanks
Form what I understand ReactiveClientRegistrationRepository is not available since you are not using a reactive stack, and here's how you can set up WebClient to be used in a Servlet environment.
Setup application properties so Spring autowires ClientRegistrationRepository and OAuth2AuthorizedClientRepository for you.
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://xxxxx.xxxxxxx.net/auth/oauth/v2/token
spring.security.oauth2.client.registration.ei-gateway.client-id=xxx-xxxx-43e9-a407-xxxxx
spring.security.oauth2.client.registration.ei-gateway.client-xxxxxx-3d21-4905-b6e5-xxxxxxxxxx
spring.security.oauth2.client.registration.ei-gateway.provider=my-oauth-provider
spring.security.oauth2.client.registration.ei-gateway.scope=read,write
spring.security.oauth2.client.registration.ei-gateway.authorization-grant-type=client_credentials
Setup configuration to indicate that your application needs to act as an oauth2 Client
#EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Client();
}
}
Expose WebClient bean configured to use client credentials
#Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
#Bean
WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(
oAuth2AuthorizedClientManager);
// default registrationId - Only if you are not using the webClient to talk to different external APIs
oauth2Client.setDefaultClientRegistrationId("ei-gateway");
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
Now you can use WebClient in your code to access external protected resources.
references:
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2client
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2Client-webclient-servlet
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#defaulting-the-authorized-client
This set up worked for me when the application is not configured as a resource server, I had to use a different configuration when the application needs to use WebClient, but also configured to be a resource server.
Hi am migrating my application from jrun to websphere server and it has functionality of asynchronous messaging usnig message listener.
public void startMessageListener(final String queueName,
final MessageListener listener) throws Exception {
QueueSession queueSession = createNewQueueSession();
Queue queue = (Queue) queueContext.lookup(queueName);
QueueReceiver queueReceiver = queueSession.createReceiver((queue));
queueReceiver.setMessageListener(listener);
//LOG Forging fix-Fortify Scan TTP 345546 -START
log.debug("started queue " + queueName);
//LOG Forging fix-Fortify Scan TTP 345546 -END
}
when i use same code in websphere it throws error javax.jms.IllegalStateException: Method setMessageListener not permitted
Because the JMS spec does not allow you to use this feature in a JEE Container.
Please help me to make it work with less code changes.
On Mac with Oracle java "1.8.0_45" I have create a Jetty base dir with:
# java -jar /Users/afarber/jetty-distribution-9.3.10.v20160621/start.jar jetty.home=/Users/afarber/jetty-distribution-9.3.10.v20160621 jetty.base=/Users/afarber/jetty-base --add-to-startd=http,servlet,webapp,resources,ext,fcgi,websocket,proxy-protocol,deploy
INFO: ext initialised in ${jetty.base}/start.d/ext.ini
INFO: resources initialised in ${jetty.base}/start.d/resources.ini
INFO: server initialised (transitively) in ${jetty.base}/start.d/server.ini
INFO: http initialised in ${jetty.base}/start.d/http.ini
INFO: servlet initialised in ${jetty.base}/start.d/servlet.ini
INFO: fcgi initialised in ${jetty.base}/start.d/fcgi.ini
INFO: proxy-protocol initialised in ${jetty.base}/start.d/proxy-protocol.ini
INFO: webapp initialised in ${jetty.base}/start.d/webapp.ini
INFO: websocket initialised in ${jetty.base}/start.d/websocket.ini
MKDIR: ${jetty.base}/lib
MKDIR: ${jetty.base}/lib/ext
MKDIR: ${jetty.base}/resources
MKDIR: ${jetty.base}/webapps
INFO: Base directory was modified
Then I have put $JETTY_BASE/webapps/ws-servlet-0.1-SNAPSHOT.war produced by the very simple Maven project out of -
WsServlet.java
public class WsServlet extends WebSocketServlet
{
#Override
public void configure(WebSocketServletFactory factory) {
factory.register(EchoListener.class);
}
}
EchoListener.java
public class EchoListener implements WebSocketListener {
private static final Logger LOG = Log.getLogger(EchoListener.class);
private Session mSession;
#Override
public void onWebSocketConnect(Session session) {
LOG.info("onWebSocketConnect {}", session);
mSession = session;
}
#Override
public void onWebSocketText(String message) {
LOG.info("onWebSocketText {}", message);
if (mSession != null && mSession.isOpen()) {
mSession.getRemote().sendString("ECHO: " + message, null);
}
}
}
Finally I have created the $JETTY_BASE/webapps/ws.xml file pointing to the WAR-file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/ws</Set>
<Set name="war"><SystemProperty name="jetty.base"/>/webapps/ws-servlet-0.1-SNAPSHOT.war</Set>
</Configure>
When I start Jetty and then connect to it using simple JavaScript code in browser var ws = new WebSocket("//127.0.0.1:8080/ws"); or the Simple Web Socket Client extension for Chrome the error comes:
# java -Dorg.eclipse.jetty.LEVEL=DEBUG -jar /Users/afarber/jetty-distribution-9.3.10.v20160621/start.jar jetty.base=/Users/afarber/jetty-base
....
WARN:oejs.ProxyConnectionFactory:qtp1993134103-12: Bad character 13 for SelectChannelEndPoint#26ba5622{/127.0.0.1:49883<->8080,Open,in,out,-,-,0/30000,ProxyConnection#49376d8e}{io=1/0,kio=1,kro=1}
Here is the full Jetty log, what have I missed here please?
UPDATE:
I have also tried connecting to ws://127.0.0.1:8080/ws-servlet-0.1-SNAPSHOT and tried adding annotations like #WebServlet(name = "WsServlet", urlPatterns = { "/ws" })- but that does not help. Also I have tried the older version 9.3.9.v20160517.
UPDATE 2:
Is the root cause the PROXY Protocol, which I have to use at my production server, because I offload SSL and normal connections to HAProxy? From the doc I read that 13 is sent as the first byte.
UPDATE 3:
The problem has been solved by adding a trailing slash: ws://127.0.0.1:8080/ws/
I have to implement two simples java projects ; the first is an EJB projectwho contains a simple service which implement a remote interface, and the second project is a java client which try to call this ejb project ,
so here is what I did until now :
Context context = new InitialContext(jndiProperties);
TestServiceRemote proxy = (TestServiceRemote) context
.lookup("java:global/testEJB/TestService!services.TestServiceRemote");
System.out.println(proxy.showHello());
and this my ejb service :
#Stateless
public class TestService implements TestServiceRemote {
public TestService() {
}
#Override
public String showHello() {
return "Hello";
}
}
finally this my Remote interface :
#Remote
public interface TestServiceRemote {
public String showHello();
}
I had deployed the EJB in WIldfly 9 , but when I launch the java client i get this error shown in console :
Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at swing.testClient.main(testClient.java:22)
Can someone tell me what I had wrong in my code ?
The java: namespace is not available by default in Java. You can either package your main class as an application client JAR inside an EAR and run it using an application client container launcher, or you can configure the InitialContext to have access to the java: namespace as described in this blog post.
I'm trying to develop a custom JAAS login module, which consumes a token and get's the user data from different sources.
It should work as an authentication realm for wildfly 8.2.1 final. I've got a test servlet in which I want to authenticate so the allowed roles for a injected EJB is checked.
The test from this site: http://www.radcortez.com/custom-principal-and-loginmodule-for-wildfly/ In fact I even started with his git project.
Because I only use a token, I can not use request.login(username, password) to initiate the wildfly login process. So I tried this:
#Inject
private SampleEJB sampleEJB;
...
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String token = request.getParameter("token");
try{
context = new LoginContext("TokenLoginDomain", new TokenCallbackHandler(token));
context.login();
}catch(Exception e){
e.printStackTrace();
}
response.getWriter().println("username=" + exampleEJB.getPrincipalName());
}
My EJB looks like this:
#Stateless
public class SampleEJB {
#Resource
private EJBContext ejbContext;
#RolesAllowed("partner")
public String getPrincipalName() {
return ejbContext.getCallerPrincipal().getName();
}
}
How do I start the login process without credentials in a servlet, so the user is logged in as wildfly user?
You can't authenticate that way in Java EE. With the given code you'll only be authenticated within the LoginContext instance.
As you already found out request.login(username, password) triggers the authentication process, but it's limited to the username/password credential.
In this case you should not only write a custom LoginModule (identity store), but a custom authentication mechanism as well. Authentication mechanisms are the controllers so to speak in the authentication process, while the identity store is the model.
Custom authentication mechanisms can be added via the JASPIC SPI, which WildFly supports well.
You can register a ServerAuthModule (SAM) from the app with some utility code that you can copy from here: https://github.com/arjantijms/glassfish-sam-ee-namespaces/tree/master/src/main/java/javax/security/authenticationmechanism
Then actually register the SAM with code as shown here:
https://github.com/arjantijms/glassfish-sam-ee-namespaces/blob/master/src/main/java/test/SamAutoRegistrationListener.java