SseEmitter onError method behaves different in Tomcat and Glassfish/Payara - java

I'm implementing server sent events in Spring MVC application with Payara 5. However, when there is error on emitter.send() (when client disconnected) emitter's onError method doesn't get called. When I try the same code on Spring Boot with embedded Tomcat everything works normal. Spring dependency versions are same on both applications.
#GetMapping("/listen-sse")
public SseEmitter sseEmitter() {
SseEmitter emitter = new SseEmitter(0L);
emitter.onError(e -> System.out.println("OnError"));
ExecutorService service = Executors.newCachedThreadPool();
service.execute(() -> {
while (true) {
try {
Thread.sleep(2000);
emitter.send("Hello");
} catch (IOException | InterruptedException e) {
System.out.println("Exception");
break;
}
}
});
service.shutdown();
return emitter;
}
My dependencies in Spring MVC application:
<dependencies>
<!--Spring resources-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- Spring + aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
</dependencies>

Related

Spring cache Caffeine integration without SpringBoot

I want to integrate Caffeine Cache in my Spring 5 application. I know that I need the CaffeineCacheManager, but i dont have the class. The only way i found is to add the SpringBoot Starter Cache package to the pom, but i dont want to use Spring Boot.
I have this Spring packages in my pom:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.3.3.RELEASE</version>
</dependency>
Is any way to have CaffeineCacheManager class wihouth Spring Boot? Thanks.
Actually i am using this code to configure the cache:
#Bean
public CacheManager cacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Arrays.asList(
new ConcurrentMapCache(
"categorias",
Caffeine.newBuilder().expireAfterWrite(Duration.ofDays(1)).maximumSize(100).build().asMap(),
false
),
new ConcurrentMapCache(
"ciudad",
Caffeine.newBuilder().maximumSize(100).build().asMap(),
false
)
));
return cacheManager;
}
The main spring cache implementation is located in spring-context dependency. You should only setup that cache manager and use #Cacheable annotation.
For examples see: https://www.baeldung.com/spring-cache-tutorial
Let me know if you need code example of connection Caffeine cache with spring cache mechanism.
CaffeineCacheManager configuration:
CaffeineCacheManager is located in
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
And caffeine dependency:
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.8</version>
</dependency>
Configuration:
#Configuration
#EnableCaching
public class Config {
#Bean
public Caffeine<Object, Object> caffeineConfig() {
return Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.MINUTES);
}
#Bean
public CacheManager cacheManager(Caffeine<Object, Object> caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}

Schedule Task with Jax-RS and CDI

I'm try to understand how to manage scheduled tasks in my project with Jax-RS and CDI.
With Spring I was easily able to achive that with ThreadPoolTaskScheduler or #Scheduled annotation and I'm trying to replicate both ways without success.
First of all, I'm using Wildfly 14 and this seems to cause some issues because I've tryied to inject with #Resource both ManagedScheduledExecutorService and TimerService but Wildfly throws exception of missing dependencies (but the Admin guide didn't help me about that).
Instead of inject resources I've tryied to use a singleton object like this:
#Singleton
public class CacheManager {
private final static Logger log = LogManager.getLogger();
public CacheManager() {
log.error("######## Init" + LocalTime.now());
}
#Schedule(hour = "*", minute = "*", second = "*/1")
private void timeout() {
log.error("######## " + LocalTime.now());
}
}
But the method is never called.
So I'm not understanding what I'm missing. Maybe I have wrongly configured the project so this is my pom.xml dependencies:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
<!-- Import the JAX-RS API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.10.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.12.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>3.0.12.Final</version>
<scope>provided</scope>
</dependency>
<!-- Import the CDI API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- Import the JSF API, we use provided scope as the API is included in JBoss WildFly -->
<dependency>
<groupId>org.jboss.spec.javax.faces</groupId>
<artifactId>jboss-jsf-api_2.2_spec</artifactId>
<version>2.2.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
This is my beans.xml
<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" bean-discovery-mode="annotated">
</beans>
I am using Java 8.
EDIT: the CacheManager is instantiated in the JAX-WS Application
#ApplicationScoped
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
private static final Logger logger = LogManager.getLogger();
private Set<Object> singletons = new HashSet<Object>();
private HashSet<Class<?>> classes = new HashSet<Class<?>>();
public JaxRsActivator() {
singletons.add(new CorsFilter());
singletons.add(new CacheManager());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
#Override
public HashSet<Class<?>> getClasses(){
return classes;
}
}
I've found the solutions: #Singleton must be javax.ejb.Singleton and not javax.inject.Singleton.

wildfly swarm: lookup ejb remote interface

I have generated two simple wildfly swarm projects. First has EJB facade with Remote interface, second should lookup it and send message. So second should be as client.
I am used
Wildfly swarm version 2017.9.4
My EJB facade lookup paths:
java:global/ejb-one/PingFacade!io.project.core.interfaces.PingFacadeRemote
java:app/ejb-one/PingFacade!io.project.core.interfaces.PingFacadeRemote
java:module/PingFacade!io.project.core.interfaces.PingFacadeRemote
java:jboss/exported/ejb-one/PingFacade!io.project.core.interfaces.PingFacadeRemote
java:global/ejb-one/PingFacade
java:app/ejb-one/PingFacade
java:module/PingFacade
My client :
public static void main(String[] args) {
BackendConnectionManager manager = new BackendConnectionManager();
try {
manager.getPingFacadeRemote().savePingMessage("halloooooo");
} catch (NamingException ex) {
Logger.getLogger(BackendConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public PingFacadeRemote getPingFacadeRemote() throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
//jndiProperties.put(Context.PROVIDER_URL,"http://localhost:8080");
final Context context = new InitialContext(jndiProperties);
return (PingFacadeRemote) context
.lookup("java:global/ejb-one/PingFacade!io.project.core.interfaces.PingFacadeRemote");
}
Added client dependencies to pom.xml
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>ejb-remote</artifactId>
</dependency>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-naming</artifactId>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-ejb-client</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-api</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.xnio</groupId>
<artifactId>xnio-nio</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.remoting3</groupId>
<artifactId>jboss-remoting</artifactId>
<version>3.3.3.Final</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.sasl</groupId>
<artifactId>jboss-sasl</artifactId>
<scope>runtime</scope>
<version>1.0.5.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.marshalling</groupId>
<artifactId>jboss-marshalling-river</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.jms</groupId>
<artifactId>jboss-jms-api_2.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.2_spec</artifactId>
<scope>runtime</scope>
</dependency>
I do not what is whole dependencies for client and always has
javax.naming.CommunicationException: WFNAM00018: Failed to connect to remote host [Root exception is org.jboss.remoting3.ServiceOpenException: Unknown service name]
at org.wildfly.naming.client.remote.RemoteContext.getRemoteTransport(RemoteContext.java:80)
at org.wildfly.naming.client.remote.RemoteContext.lambda$lookupNative$0(RemoteContext.java:106)
at org.wildfly.naming.client.NamingProvider.performExceptionAction(NamingProvider.java:150)
at org.wildfly.naming.client.remote.RemoteContext.lookupNative(RemoteContext.java:104)
at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:74)
at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:60)
at org.wildfly.naming.client.WildFlyRootContext.lookup(WildFlyRootContext.java:150)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at io.project.ejbtwo.rest.BackendConnectionManager.getPingFacadeRemote(BackendConnectionManager.java:57)
at io.project.ejbtwo.rest.BackendConnectionManager.main(BackendConnectionManager.java:43)
Caused by: org.jboss.remoting3.ServiceOpenException: Unknown service name
Also how to solve problem with passing security credentials in client lookup?
Projects by itself here
https://drive.google.com/open?id=0B45Md1_c5-gGQ0p3Q2pURUxOY00
In BackendConnectionManager.java, line 57, you are trying to look up the service java:global/ejb-one/PingFacade!io.project.core.interfaces.PingFacadeRemote, but it seems to not exist. PingFacadeRemote interface is a part of ejb-core module. Yes, it is true that you implement it in ejb-one module, but you registered the interface as a remote (#Remote(PingFacadeRemote.class), in PingFacade.java).
You might try to replace it with java:global/ejb-core/PingFacade!io.project.core.interfaces.PingFacadeRemote.

Camel context not starting in hello world app

I am attempting to run camel within spring. Below are the files i have..
POM xml file which have relevant dependencies.
<properties>
<spring.version>3.2.11.RELEASE</spring.version>
<camel.version>2.14.1</camel.version>
</properties>
<?xml version="1.0" encoding="UTF-8"?>
<dependencies>
<!-- camel core -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-metrics</artifactId>
<version>${camel-version}</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Main context file (main-context.xml).
<camel:camelContext trace="false" id="mc-service-camel-context" threadNamePattern="Camel (#camelId#) thread ##counter# - #name#">
<camel:contextScan/>
</camel:camelContext>
A route that looks like this
#Component
public class MyRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer://runOnce?repeatCount=1&delay=5000")
.log("Hello World!!")
.end();
}
}
And finally a main class that looks like this.
public static void main(String[] args) throws InterruptedException {
AbstractXmlApplicationContext appContext = new ClassPathXmlApplicationContext("main-context.xml");
Thread.sleep(100000);
}
Issue is i don't see the log "Hello World". Could someone give me some feedback on what i am missing..
I had to enable Component scanning.
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.app*" />

Spring 3 with Drools 6 maven inconcistency

I have a problem integrating Drools with Spring. I am trying to make a simple Hello World spring example, I reached a moment where my simple project refuses to compile.
To work with Drools annotations like #KSession I need the drools-spring package, but it seems incompatible with Spring 3. As builder I use Maven. Here is how my .pom's looks like:
<dependencies>
<!-- Drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-spring</artifactId>
<version>6.0.0.Beta2</version>
</dependency>
<!-- Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
</dependencies>
I use very simple case of controller class:
#Controller
#RequestMapping(value = "/")
public class BaseController extends AbstractController {
private static final Logger log = Logger.getLogger(BaseController.class);
#Autowired
#KSession("ksession-rules")
KieSession mySession;
#RequestMapping(value = "/test")
public #ResponseBody
String test() {
Fact myFact = new Fact();
myFact.setFactNumber(20); //According to my rule when myFact.number>20
//then result will be set to "Hello World"
mySession.insert(myFact);
mySession.fireAllRules();
return myFact.getResult();
}
}
At this point I receive an error:
"The hierarchy of the type BaseController is inconsistent".
I noticed that if I remove drools-spring from the dependency list the project compiles successfully. However without that package I cannot deploy my project, because the deployer demands the drools' class responsible for interpreting #KSession and that class is located in drools-spring package.
After some investigation it appears that my Drools session configuration seems to have
nothing to do with the error above, so for the sake of succinctness I will not quote them. Instead of that I will mark that even if I don't make any modifications to the spring configuration and remove the KieSession from my example, making it a simple spring hello world example, I receive one and the same error out of my IDE (Eclipse): "The hierarchy of the type BaseController is inconsistent" and if I remove the drools-spring dependency the problem disappears.
It seems to me as dependency conflict.
Does anyone experienced similar problems with drools+spring?
Can someone suggest a solution to the problem?
Am I doing something wrong?
Thanks for the help!
After some research I found two things.
Drools' drools-spring package declares its own spring dependencies that are overriding my spring dependencies, which leads to spring malunctions. What I did is to manually remove the spring dependencies from drools-spring .pom file.
Another mistake that I had in the upper example is that I didn't have kie-spring as dependency. Kie-spring is mandatory for one drools bean KModuleBeanFactoryPostProcessor, which is responsible to read my kmodule-kbase-ksession configuration from the spring configuration.
After resolving these two problems my project compiles now and I can see in the code that KModuleBeanFactoryPostProcessor defines that my configuration is being read and analized as I expected it to be.

Categories

Resources