Can I invoke a local bean into a ear file from a Javax-WS into a war file- apache-tomee-plus-1.7.4 - spring

I am using Eclipse Mars 2, maven 3.3.9 and apache-tomee-plus-1.7.4.
I have 2 projects (A and B)
Project A is a Web Service compiled like a WAR using maven 3.3.9 and deployed into TOMEE_HOME/webapps
Project B is an EJB module compiled like a EAR using maven 3.3.9 and deployed into TOMEE_HOME/apps (this project include other project with ejb clasess and compiled like a jar file)
These projects do not depend on each other in the pom.xml but I need to lookup an EJB in project A from project B.
---------- Project B Implementation -----------
Local Bean Interface in project B:
package co.edu.uniquindio.model.ejb.interfaces;
import javax.ejb.Local;
import org.springframework.context.support.ClassPathXmlApplicationContext;
#Local
public interface IReporte {
public Object generate1();
public Object generate2();
public void setContext(ClassPathXmlApplicationContext context);
}
Implement local bean interface in project B:
package co.edu.uniquindio.model.ejb;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import co.edu.uniquindio.model.ejb.interfaces.IReporte;
#Stateless
#EJB(beanInterface = IReporte.class, beanName="ReporteEJB", name="IReporte")
public class ReporteEJB implements IReporte{
private ClassPathXmlApplicationContext context;
#Override
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public Object generate1(){
// do somthing amazing
}
#Override
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public Object generate2(){
// do somthing amazing
}
#Override
public void setContext(ClassPathXmlApplicationContext context) {
this.context = context;
}
}
---------- Project A Implementation -----------
The way that I develop lookup is:
package co.swatit.rest.services;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import co.edu.uniquindio.model.ejb.interfaces.IReporte;
#Path("/ReporteWS")
public class ReporteWS {
#POST
#Path("generate1and2")
#Produces(MediaType.APPLICATION_JSON)
#Consumes({ MediaType.APPLICATION_JSON} )
public Response generate1and2() {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
try {
Context ctx = new InitialContext(props);
// I do not know if use IReporte or ReporteEJB to cast. and I do not know how to import it.
IReporte ejbLocal = (IReporte) ctx.lookup("java:global/Sac-report-ear-1.0.0/co.swatit-Sac-report-ejb-1.0.0/ReporteEJB");
ejbLocal.generate1();
ejbLocal.generate2();
} catch (Exception exception) {
exception.printStackTrace()
}
return Response.status(Status.OK)
.entity(ejbLocal).build();
}
}
I do not know if it is possible import the local bean in project A to lookup that bean:
import co.edu.uniquindio.model.ejb.interfaces.IReporte
I do not know if use IReporte or ReporteEJB to cast, and I do not know how to import it.
Thank you for your help.

Related

Spring: ApplicationStartingEvent cannot be cast to ApplicationPreparedEvent for OptaPlanner Examination App

I'm a newbie and I try to start a Spring application linked to Optaplanner which will solve and place exams on a timetable.
I fixed the various issues with missing jars and I started the app on main.
However, it gives error:
Exception in thread "main" java.lang.ClassCastException: class org.springframework.boot.context.event.ApplicationStartingEvent cannot be cast to class org.springframework.boot.context.event.ApplicationPreparedEvent (org.springframework.boot.context.event.ApplicationStartingEvent and org.springframework.boot.context.event.ApplicationPreparedEvent are in unnamed module of loader 'app')
Here is the TimeTable class :
package models;
import java.util.List;
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty;
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
#PlanningSolution
public class Timetable {
#ValueRangeProvider(id = "PeriodeRange")
#ProblemFactCollectionProperty
public List<Periode> periodeList;
#ValueRangeProvider(id = "SalleRange")
#ProblemFactCollectionProperty
public List<Salle> salleList;
#PlanningEntityCollectionProperty
public List<Examen> examenList;
#PlanningScore
public HardSoftScore score;
public void TimeTable(List<Periode> periodeList, List<Salle> roomList,
List<Examen> examenList) {
this.periodeList = periodeList;
this.salleList = roomList;
this.examenList = examenList;
}
public List<Periode> getperiodeList() {
return periodeList;
}
public List<Salle> getsalleList() {
return salleList;
}
public List<Examen> getexamenList() {
return examenList;
}
public HardSoftScore getScore() {
return score;
}
}
And the class that defines the solver :
package models;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import modeles.Timetable;
import org.optaplanner.core.api.solver.SolverJob;
import org.optaplanner.core.api.solver.SolverManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/Timetable")
public class TimetableController {
#Autowired
public SolverManager<Timetable, UUID> solverManager;
#PostMapping("/solve")
public Timetable solve(#RequestBody Timetable problem) {
UUID problemId = UUID.randomUUID();
// Submit the problem to start solving
SolverJob<Timetable, UUID> solverJob = solverManager.solve(problemId, problem);
Timetable solution;
try {
// Wait until the solving ends
solution = solverJob.getFinalBestSolution();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException("Solving failed.", e);
}
return solution;
}
}
And here is the main :
package models;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TimeTableSpringBootApp {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(TimeTableSpringBootApp.class, args);
}
}
Any answer would be gladly appreciated.
Thank you in advance.
I suspect your project's dependency tree somehow has that spring class ApplicationStartingEvent twice in it's classpath (coming from different jars), which causes the class cast exception.
Try running mvn dependency:tree on your project and the optaplanner spring boot school timetabling quickstart. I suspect you're mixing spring versions in your dependency tree.

Bean Creation or defining is failing in springboot

Main Class
package com.prac.sdp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.prac.sdp.pdf.PdfGenerator;
#SpringBootApplication
public class SdpApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(SdpApplication.class, args);
PdfGenerator pdg=ctx.getBean(PdfGenerator.class);
pdg.pdfgenerate();
}
}
PdfGenerator.java
package com.prac.sdp.pdf;
import java.io.FileNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
#Component
public class PdfGenerator {
#Autowired
PdfWriter writer; <------ Autowiring is not working here I don't know why.
}
Issue -- Consider defining a bean of type 'com.itextpdf.kernel.pdf.PdfWriter' in your
configuration.
Resolution tried:
Used #ComponentScan("com.itextpdf") --> Started getting Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
'com.prac.sdp.pdf.PdfGenerator' available.
Let me know how this issue can be fixed I am stuck at this. Thanks in advance.
create bean with #Bean annotation tag , as this is from third party library , you need to define by Method.
#Bean
public PdfWriter writer(){
return new PdfWriter();
}
Add above method to your SdpApplication class.

Asserting log messages using Mockito, TestNG and Log4j2

I've been following asserting-log-messages-with-log4j2-and-mockito to write TestNG test to test logging for Log4j2. Most of what is written in the post seems to work. However, when I'm running my test I'm getting:
Wanted but not invoked:
appender.append(<Capturing argument>);
-> at LoggingTest.test(LoggingTest.java:105)
However, there were exactly 2 interactions with this mock:
appender.getName();
-> at org.apache.logging.log4j.core.config.AbstractConfiguration.addAppender(AbstractConfiguration.java:603)
appender.getName();
-> at org.apache.logging.log4j.core.config.AppenderControl.<init>(AppenderControl.java:51)
My TestNGclass is:
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.mockito.ArgumentCaptor;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class LoggingTest {
private Appender appender;
private ArgumentCaptor<LogEvent> captor;
#BeforeMethod
public void setUp() {
appender = mock(Appender.class);
captor = ArgumentCaptor.forClass(LogEvent.class);
reset(appender);
when(appender.getName()).thenReturn("Appender");
when(appender.isStarted()).thenReturn(true);
when(appender.isStopped()).thenReturn(false);
LoggerContext context = (LoggerContext)LogManager.getContext();
Configuration config = context.getConfiguration();
config.addAppender(appender);
LoggerConfig rootConfig = config.getRootLogger();
rootConfig.setLevel(Level.INFO);
rootConfig.addAppender(appender, Level.INFO, null);
context.updateLoggers();
}
#Test
public void test() {
LogManager.getLogger().info("testing");
verify(appender).append(captor.capture());
LogEvent logEvent = captor.getValue();
assertThat(logEvent.getMessage()).isEqualTo("test");
}
}
I've been looking at this for a while and have not been able to find a my error. Could someone point me in the right direction?

Spring Boot & Hibernate Validation's ConstraintMappingContributor

The hibernate validations documentation describes how to create ConstraintMappingContributors here.
It states:
You then need to specify the fully-qualified class name of the
contributor implementation in META-INF/validation.xml, using the
property key hibernate.validator.constraint_mapping_contributors. You
can specify several contributors by separating them with a comma.
Given I have many of these, what would be the most appropriate way to auto-discover these i.e. via #Component and add them dynamically at runtime to the ConstrainMappingConfiguration during Spring Boot startup.
For example.. if a developer creates a new ConstraintMappingContributor, it should be picked up and added automatically when spring boot starts, requiring no other file changes.
This is what I came up with, seems to be working for me.
package...
import org.hibernate.validator.spi.cfg.ConstraintMappingContributor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
#Configuration
public class ValidationConfiguration {
private final List<ConstraintMappingContributor> contributors;
public ValidationConfiguration(Optional<List<ConstraintMappingContributor>> contributors) {
this.contributors = contributors.orElseGet(ArrayList::new);
}
#Bean
public LocalValidatorFactoryBean validatorFactory() {
return new ValidatorFactoryBean(this.contributors);
}
}
package...
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
import org.hibernate.validator.spi.cfg.ConstraintMappingContributor;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.validation.Configuration;
import java.util.List;
public class ValidatorFactoryBean extends LocalValidatorFactoryBean {
private final List<ConstraintMappingContributor> contributors;
ValidatorFactoryBean(List<ConstraintMappingContributor> contributors) {
this.contributors = contributors;
}
#Override
protected void postProcessConfiguration(Configuration<?> cfg) {
if (cfg instanceof HibernateValidatorConfiguration) {
HibernateValidatorConfiguration configuration = (HibernateValidatorConfiguration) cfg;
this.contributors.forEach(contributor -> contributor.createConstraintMappings(() -> {
DefaultConstraintMapping mapping = new DefaultConstraintMapping();
configuration.addMapping(mapping);
return mapping;
}));
}
}
}
I invoke it like this...
if(SpringValidatorAdapter.class.isInstance(this.validatorFactory)){
SpringValidatorAdapter.class.cast(this.validatorFactory).validate(entity, errors);
}

Running JAX-RS in Netbeans 8.1 EJB project

I created a Java EE 7 application using Netbeans 8.1 (Maven project), having an EJB project and a Web project. I added an ApplicationConfig extending javax.ws.rs.core.Application and marked auto-generated NewSessionBean with javax.ws.rs.GET and javax.ws.rs.Path in the EJB project.
Now, when I right click on the EJB project and RUN it, it gets deployed on the Glassfish server, but I can't access REST resource. Here is the JAX-RS config file:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class JaxrsAppConfig extends Application {
}
Here is my JAX-RS resource:
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Stateless
#LocalBean
#Path("/demo")
public class NewSessionBean {
#GET
#Produces(MediaType.APPLICATION_XML)
public Person businessMethod() {
return new Person(1, "Prakhar Mishra", 26);
}
}
I tried to access it using these URLs:
http://localhost:8080/DemoJavaEE7-ejb/api/demo
http://localhost:8080/DemoJavaEE7-web/api/demo
http://localhost:8080/api/demo
But, getting regular 404 page. Could anybody please tell me what might be the problem here?
You should registered you service.
Try to change your config like:
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("org.foo.rest;org.bar.rest");
}
}
More details https://jersey.java.net/documentation/latest/deployment.html

Resources