I am developing a simple spring boot application in Kotlin. I have one of my service working completely fine. However when i define another service i get this error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'categoryService' defined in file [C:\Users\userName\Documents\Projects\ProjectA\backend\proj\build\classes\kotlin\main\c
om\example\test\category\service\CategoryService.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [c
om.example.test.category.service.CategoryService]: Constructor threw exception; nested exception is java.lang.IllegalStateException: FirebaseApp with name [DEFAULT] doesn't exist.
at org.springframework.beans.factory
When i remove this service, everything works fine. So adding second service causes this issue.
//Service
#Service
class CategoryService : CategoryServiceInterface {
override fun deleteCategory(userToken: String, categoryId: String): String {
return ""
}
}
//Controller
#RestController
class CategoryController {
#Autowired
lateinit var categoryService: CategoryService
#DeleteMapping("/category")
fun deleteCategory(#RequestHeader(name = "Authorization") token: String, #RequestBody categoryId: String) =
categoryService.deleteCategory(
userToken = token,
categoryId = categoryId
)
//MainApp
#SpringBootApplication
class MainApplication
fun main(args: Array<String>) {
SpringApplication.run(MainApplication::class.java, *args)
}
FirebaseInitializer
#Service
class FirebaseInitializer {
#PostConstruct
fun initialize() {
try {
val serviceAccount = ClassPathResource("serviceaccount.json")
val options = FirebaseOptions
.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount.inputStream))
.setDatabaseUrl("https://databaseurl.firebaseio.com")
.build()
FirebaseApp.initializeApp(options)
} catch (e: Exception) {
}
}}
I used this article to set up my first service https://medium.com/techwasti/spring-boot-firebase-crud-b0afab27b26e
If i remove this second service, my first service works completely fine. Any help would be greatly appreciated
So i found the problem, If i initialize the firebase with the way mentioned in the article above as a service and using post construct, it gives me the above issues.
I moved my firebase initialize code in my Spring boot application class and everything now works as expected.
#SpringBootApplication
class FoodiesApplication
fun main(args: Array<String>) {
try {
val serviceAccount = ClassPathResource("serviceaccount.json")
val options = FirebaseOptions
.builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount.inputStream))
.setDatabaseUrl("https://databaseurl.firebaseio.com")
.build()
FirebaseApp.initializeApp(options)
} catch (e: Exception) {
}
SpringApplication.run(FoodiesApplication::class.java, *args)
}
Just add #Lazy annotation to bean.
I'm trying to test an application with the following binding configured:
spring:
cloud:
stream:
bindings:
accountSource:
destination: account
producer:
useNativeEncoding: true
kafka:
binder:
brokers: ${KAFKA_BOOTSTRAP_ADDRESSES}
producer-properties:
schema.registry.url: ${KAFKA_SCHEMA_REGISTRY_URL}
value.subject.name.strategy: io.confluent.kafka.serializers.subject.RecordNameStrategy
bindings:
accountSource:
producer:
configuration:
key:
serializer: org.apache.kafka.common.serialization.StringSerializer
value:
serializer: io.confluent.kafka.streams.serdes.avro.SpecificAvroSerializer
When running the application normally, AbstractMessageChannel.interceptorList is empty and sending message to broker works fine.
When running the test (with spring-cloud-stream-test-support binder), AbstractMessageChannel.interceptorList gets populated with MessageConverterConfigurer and message is being converted using content-type serialization mechanisms (Avro object is converted to JSON). This is the test code:
#RunWith(SpringRunner.class)
public class AccountServiceImplTest {
#Autowired
private AccountService accountService;
#Autowired
private MessageCollector messageCollector;
#Autowired
private MessageChannel accountSource;
#Test
public void create() {
// Simplified code
AccountCreationRequest accountCreationRequest = AccountCreationRequest.builder().company(company).subscription(subscription).user(user).build();
accountCreationRequest = accountService.create(accountCreationRequest);
Message<?> message = messageCollector.forChannel(accountSource).poll();
// execute asserts on message
}
#TestConfiguration
#ComponentScan(basePackageClasses = TestSupportBinderAutoConfiguration.class)
static protected class AccountServiceImplTestConfiguration {
#EnableBinding({KafkaConfig.AccountBinding.class})
public interface AccountBinding {
#Output("accountSource")
MessageChannel accountSource();
}
}
Am I missing something to disable spring-cloud-stream serialization mechanisms?
Don't use the test binder; use the Kafka binder with an embedded kafka broker instead.
is it possible to create and consume the same corda state in one flow or create and consume it in different subflows?
I get the following error:
Caused by: net.corda.core.flows.NotaryException: Unable to notarise transactionBEDE8C3F8F2D7A646A9F7D1948DAF77CDAFC37F3B086E09FC766F0D412F02690: One or more input states have been used in another transaction
Yes, you can create and consume the same Corda state in a single flow.
You need to proceed in two steps:
Create a first transaction issuing the new state
Create a second transaction consuming the new state
Note that if you create the second transaction and cause a counterparty to call ResolveTransactionFlow on it before finalising the first transaction, this will cause a TransactionResolutionException, because you don't have the first transaction in your storage to distribute yet. This can occur for example when running CollectSignaturesFlow.
Here is an example of building two transactions in the same flow:
#InitiatingFlow
#StartableByRPC
class TwoTransactionsFlow(val otherParty: Party) : FlowLogic<Unit>() {
#Suspendable
override fun call() {
val otherPartySessions = listOf(initiateFlow(otherParty))
val transactionBuilderOne = TransactionBuilder()
// TODO: Add notary and transaction components.
val partSignedTransactionOne = serviceHub.signInitialTransaction(transactionBuilderOne)
val fullySignedTransactionOne = subFlow(CollectSignaturesFlow(partSignedTransactionOne, otherPartySessions))
val notarisedTransactionOne = subFlow(FinalityFlow(fullySignedTransactionOne))
val transactionOneFirstOutputRef = StateRef(notarisedTransactionOne.id, 0)
val transactionOneFirstOutput = serviceHub.toStateAndRef<ContractState>(transactionOneFirstOutputRef)
val transactionBuilderTwo = TransactionBuilder()
.addInputState(transactionOneFirstOutput)
// TODO: Add notary and other transaction components.
val partSignedTransactionTwo = serviceHub.signInitialTransaction(transactionBuilderTwo)
val fullySignedTransactionTwo = subFlow(CollectSignaturesFlow(partSignedTransactionTwo, otherPartySessions))
subFlow(FinalityFlow(fullySignedTransactionTwo))
}
}
Some more points to consider
In Corda 4, when creating and consuming the state in one flow, the corresponding responder flow should call ReceiveFinalityFlow 2 times(also SignTransactionFlow incase of signers), or else an error will be thrown:-java.util.concurrent.ExecutionException: net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=1984916257986245538) with empty buffer.
Code snippet of Initiator Flow in Java
...
// Signing the transaction.
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
// Creating a session with the other party.
FlowSession otherPartySession = initiateFlow(otherParty);
// Obtaining the counterparty's signature.
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
SignedTransaction notraizedtransaction = subFlow(new FinalityFlow(fullySignedTx, otherPartySession));
//------------------------------------------------------------------------------------------------------------
// STEP-2:
// SINCE NOW WE HAVE A NEW UNCONSUMED RECORD-ANCHOR SO WE MUST MAKE IT CONSUMED ( BY USING THE PREVIOUS OUTPUT AS AN INPUT)
//
//------------------------------------------------------------------------------------------------------------
StateAndRef oldStateref = getServiceHub().toStateAndRef(new StateRef(notraizedtransaction.getId(),0));
Command storeCommand = new Command<>(new AnchorStateContract.Commands.ApproveRecAnchorCmd(), requiredSigners);
TransactionBuilder txBuilder2 = new TransactionBuilder(notary)
.addInputState(oldStateref)
.addCommand(storeCommand);
txBuilder2.verify(getServiceHub());
// signing
SignedTransaction signedTx2 = getServiceHub().signInitialTransaction(txBuilder2);
// Finalising the transaction.
SignedTransaction fullySignedTx2 = subFlow(new CollectSignaturesFlow(
signedTx2, Arrays.asList(otherPartySession), CollectSignaturesFlow.Companion.tracker()));
//notarized transaction
return subFlow(new FinalityFlow(fullySignedTx2, otherPartySession));
}
Code snippet of ResponderFlow in Java
#InitiatedBy(Initiator.class)
public class Responder extends FlowLogic<SignedTransaction> {
private FlowSession otherPartySession;
public Responder(FlowSession otherPartySession) {
this.otherPartySession = otherPartySession;
}
#Suspendable
#Override
public SignedTransaction call() throws FlowException
{
//this class is used inside call function for the verification purposes before signed by this party
class SignTxFlow1 extends SignTransactionFlow
{
private SignTxFlow1(FlowSession otherPartySession) {
super(otherPartySession);
}
#Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
// Validation Logic
return null;
});
}
}
//this class is used inside call function for the verification purposes before signed by this party
class SignTxFlow2 extends SignTransactionFlow
{
private SignTxFlow2(FlowSession otherPartySession) {
super(otherPartySession);
}
#Override
protected void checkTransaction(SignedTransaction stx) {
requireThat(require -> {
// Validation Logic
return null;
});
}
}
//Validation, signing and storing of first transaction data
SecureHash expectedTxId1 = subFlow(new SignTxFlow1(otherPartySession)).getId();
subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId1));
//Validation, signing and storing of second transaction data
SecureHash expectedTxId2 = subFlow(new SignTxFlow2(otherPartySession)).getId();
return subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId2));
}
}
In my project based on Spring Boot 1.3.3, I integrated MyBatis with mybatis-spring-boot-starter 1.1.1 as persistence layer, all CRUD operation seems working fine separately, but the integration tests failed and I found the DB operation gets blocked in asynchronous task.
The test code looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SapiApplication.class)
#Transactional
public class OrderIntegrationTest {
#Test
public void shouldUpdateOrder() throws InterruptedException{
Order order1 = getOrder1();
orderService.createOrder(order1);
Order order1updated = getOrder1Updated();
orderService.updateOrderAsync(order1updated);
Thread.sleep(1000l);
log.info("find the order!");
Order order1Db = orderService.findOrderById(order1.getOrderId());
log.info("found the order!");
assertEquals("closed", order1Db.getStatus());
}
}
The expected execution order is createOrder() -> updateOrderAsync() -> findOrderById(), but actually the execution order is createOrder() -> updateOrderAsync() started and blocked -> findOrderById() -> updateOrderAsync() continued and ended.
Log:
16:23:04.261 [executor1-1] INFO c.s.api.web.service.OrderServiceImpl - updating order: 2884384
16:23:05.255 [main] INFO c.s.a.w.service.OrderIntegrationTest - find the order!
16:23:05.280 [main] INFO c.s.a.w.service.OrderIntegrationTest - found the order!
16:23:05.299 [executor1-1] INFO c.s.api.web.service.OrderServiceImpl - updated order: 2884384
Other related code:
#Service
public class OrderServiceImpl implements OrderService {
#Autowired
private OrderDao orderDao;
#Async("executor1")
#Override
public void updateOrderAsync(Order order){
log.info("updating order: {}", order.getOrderId());
orderDao.updateOrder(order);
log.info("updated order: {}", order.getOrderId());
}
}
The DAO:
public interface OrderDao {
public int updateOrder(Order order);
public int createOrder(Order order);
public Order findOrderById(String orderId);
}
The Gradle dependencies:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-jdbc'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:1.1.1'
compile 'ch.qos.logback:logback-classic:1.1.2'
compile 'org.springframework.boot:spring-boot-configuration-processor'
runtime 'mysql:mysql-connector-java'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testCompile 'org.springframework.boot:spring-boot-starter-test'
testCompile "org.springframework.security:spring-security-test"
}
The Spring configuration:
#SpringBootApplication
#EnableAsync
#EnableCaching
#EnableScheduling
#MapperScan("com.sapi.web.dao")
public class SapiApplication {
#Bean(name = "executor1")
protected Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(100);
return executor;
}
#Bean
#Primary
#ConfigurationProperties(prefix = "datasource.primary")
public DataSource numberMasterDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "secondary")
#ConfigurationProperties(prefix = "datasource.secondary")
public DataSource provisioningDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "jdbcTpl")
public JdbcTemplate jdbcTemplate(#Qualifier("secondary") DataSource dsItems) {
return new JdbcTemplate(dsItems);
}
public static void main(String[] args) {
SpringApplication.run(SapiApplication.class, args);
}
}
The properties:
mybatis.mapper-locations=classpath*:com/sapi/web/dao/*Mapper.xml
mybatis.type-aliases-package=com.sapi.web.vo
datasource.primary.driver-class-name=com.mysql.jdbc.Driver
datasource.primary.url=jdbc:mysql://10.0.6.202:3306/sapi
datasource.primary.username=xxx
datasource.primary.password=xxx
datasource.primary.maximum-pool-size=80
datasource.primary.max-idle=10
datasource.primary.max-active=150
datasource.primary.max-wait=10000
datasource.primary.min-idle=5
datasource.primary.initial-size=5
datasource.primary.validation-query=SELECT 1
datasource.primary.test-on-borrow=false
datasource.primary.test-while-idle=true
datasource.primary.time-between-eviction-runs-millis=18800
datasource.primary.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=100)
datasource.secondary.url = jdbc:mysql://10.0.6.202:3306/xdb
datasource.secondary.username = xxx
datasource.secondary.password = xxx
datasource.secondary.driver-class-name = com.mysql.jdbc.Driver
logging.level.org.springframework.web=DEBUG
The problem you see is caused by the fact that the whole test method shouldUpdateOrder is executed in one transaction. This means that any update operation that is executed in the thread that runs shouldUpdateOrder locks the record for the whole duration of the transaction (that is till exit from test method) and that record cannot be updated by another concurrent transaction (that is executed in async method).
To solve the issue you need to change transactions boundaries. In your case the correct way to emulate real life usage is to
create order in one transaction and finish the transaction
update order in another transaction
check that update is executed as expected in yet another transaction
I'm trying to get EJB to work with Glassfish v3. I'm working on a Java EE Web application with Servlets.
When I deploy this web app to Glassfish, it registers the EJB class into the
java:global JNDI tree. But, when I try to inject an instance of this into my
Servlet I got a NameNotFoundException.
When I look at the logs of my server, the Servlet tries to do the look up in java:comp/env.
Can someone help me to solve this?
Relevant code for the login part:
UserDao.java
#Local
public interface UserDao {
public User find(Long id);
public List<User> findAll();
public List<User> paginate(int offset, int nbentry) throws IllegalArgumentException, IllegalStateException;
public User findUserByUsernameAndPassword(String username, String password);
public User create(User user) throws UserException;
public User update(User user) throws UserException;
public Boolean delete(User user) throws UserException;
public int count();
}
JpaUserDao.java
#Stateless
public class JpaUserDao implements UserDao {
private Logger log = Logger.getLogger(JpaUserDao.class.getSimpleName());
#PersistenceContext(unitName = "YouFood-PU")
private EntityManager em;
#Override
public User create(User user) throws UserException {
try {
em.persist(user);
} catch (Exception e) {
throw new UserException("Creation of the user: " + user
+ " failed, please try later or contact the webmaster");
}
return user;
}
#Override
public User update(User user) throws UserException {
try {
em.persist(em.merge(user));
} catch (Exception e) {
throw new UserException("Update of the user: " + user
+ " failed, please try later or contact the webmaster");
}
return user;
}
#Override
public Boolean delete(User user) throws UserException {
try {
em.remove(em.merge(user));
return true;
} catch (Exception e) {
throw new UserException("Deletion of the user: " + user
+ " failed, please try later or contact the webmaster");
}
}
#Override
public User find(Long id) {
User user = new User();
try {
user = em.find(User.class, id);
return user;
} catch (Exception e) {
return null;
}
}
#Override
public User findUserByUsernameAndPassword(String username, String password) {
User user = null;
try {
log.info("findUserByUsernameAndPassword");
user = (User) em
.createQuery(
"SELECT u FROM User AS u where u.username = :username AND u.password = :password ")
.setParameter("username", username)
.setParameter("password", password).getSingleResult();
return user;
} catch (Exception e) {
e.printStackTrace();
log.severe(e.getStackTrace().toString());
return null;
}
}
#SuppressWarnings("unchecked")
#Override
public List<User> findAll() {
List<User> users = null;
try {
users = (List<User>) em.createQuery("SELECT u FROM User u")
.getResultList();
return users;
} catch (Exception e) {
return null;
}
}
#SuppressWarnings("unchecked")
#Override
public List<User> paginate(int offset, int nbentry)
throws IllegalArgumentException, IllegalStateException {
List<User> users = null;
users = (List<User>) em.createQuery("FROM User").setFirstResult(offset)
.setMaxResults(nbentry).getResultList();
return users;
}
#Override
public int count() {
Number count;
count = (Number) em.createQuery("SELECT COUNT(u.id) FROM User")
.getSingleResult();
return count.intValue();
}
}
Authenticator.java
#Stateless
public class Authenticator {
private String userFullName;
private Long userId;
#EJB
private JpaUserDao userDao;
public Authenticator() {}
public AuthenticationError connect(String username, String password)
throws Exception {
String hashed_password = Authenticator.hash(password, "UTF-8");
User user = null;
user = userDao.findUserByUsernameAndPassword(username,
hashed_password);
if (user == null) {
return AuthenticationError.UserNotFound;
}
this.userFullName = user.toString();
this.userId = user.getId();
return AuthenticationError.Success;
}
public Boolean disconnect(HttpSession session) throws Exception {
try {
session.invalidate();
return true;
} catch (Exception e) {
return false;
}
}
public String getUserFullName() {
return this.userFullName;
}
public Long getUserId() {
return this.userId;
}
/**
*
* Static method
*
* #throws Exception
*
*/
public static String hash(String data, String charset) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(data.getBytes(charset), 0, data.length());
String hash = new BigInteger(1, md.digest()).toString(16);
return hash;
}
}
LoginServlet.java
#WebServlet("/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Logger log = Logger.getLogger(LoginServlet.class.getSimpleName());
#EJB
private Authenticator auth;
/**
* #see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
log.info("LoginServlet.deGet() call");
request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//auth = new Authenticator();
log.info("LoginServlet.dePost() call");
String message = null;
String username = request.getParameter("username");
String password = request.getParameter("password");
log.info("username: " + username);
log.info("password: " + password);
try {
AuthenticationError status = auth.connect(username, password);
System.out.println(status);
switch (status) {
case PasswordMissMatch:
message = "Password missmatch";
log.info(message);
request.setAttribute("error", message);
request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
break;
case Success:
message = "Your are successfully logged in";
log.info(message);
request.setAttribute("success", message);
request.getSession().setAttribute("loggedIn", true);
request.getSession().setAttribute("full_name", auth.getUserFullName());
request.getSession().setAttribute("user_id", auth.getUserId());
break;
case UserNotFound:
message = "Username provided not found in our record";
log.info(message);
request.setAttribute("error", message);
request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
break;
}
} catch (GeneralSecurityException e) {
message = e.getMessage();
request.setAttribute("error", message);
} catch (Exception e) {
message = e.getMessage();
request.setAttribute("error", message);
}
request.getRequestDispatcher("/home").forward(request, response);
}
}
Glassfish Deploy log
INFO: closing
ATTENTION: DPL8027: Ignore WEB-INF/sun-web.xml in archive
/Users/guillaume/Documents/workspace/Supinfo/YouFood/nbbuild/web/, as GlassFish
counterpart runtime xml WEB-INF/glassfish-web.xml is present in the same
archive.
INFO: Processing PersistenceUnitInfo [
name: YouFood-PU
...]
INFO: Binding entity from annotated class: com.youfood.entity.Menu
INFO: Bind entity com.youfood.entity.Menu on table Menu
INFO: Binding entity from annotated class: com.youfood.entity.DinningRoom
INFO: Bind entity com.youfood.entity.DinningRoom on table DinningRoom
INFO: Binding entity from annotated class: com.youfood.entity.Item
INFO: Bind entity com.youfood.entity.Item on table Item
INFO: Binding entity from annotated class: com.youfood.entity.TTable
INFO: Bind entity com.youfood.entity.TTable on table TTable
INFO: Binding entity from annotated class: com.youfood.entity.Zone
INFO: Bind entity com.youfood.entity.Zone on table Zone
INFO: Binding entity from annotated class: com.youfood.entity.Country
INFO: Bind entity com.youfood.entity.Country on table Country
INFO: Binding entity from annotated class: com.youfood.entity.User
INFO: Bind entity com.youfood.entity.User on table User
INFO: Binding entity from annotated class: com.youfood.entity.Order
INFO: Bind entity com.youfood.entity.Order on table OrderTable
INFO: Binding entity from annotated class: com.youfood.entity.Restaurant
INFO: Bind entity com.youfood.entity.Restaurant on table Restaurant
INFO: Mapping collection: com.youfood.entity.DinningRoom.zones -> Zone
INFO: Mapping collection: com.youfood.entity.Zone.tables -> TTable
INFO: Mapping collection: com.youfood.entity.Country.restaurants -> Restaurant
INFO: Mapping collection: com.youfood.entity.Restaurant.dinningRoom -> DinningRoom
INFO: Hibernate Validator not found: ignoring
INFO: Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.
INFO: Initializing connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
INFO: Using provided datasource
INFO: RDBMS: MySQL, version: 5.1.54
INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.1.13 ( Revision: ${bzr.revision-id} )
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
INFO: Transaction strategy: org.hibernate.ejb.transaction.JoinableCMTTransactionFactory
INFO: instantiating TransactionManagerLookup: org.hibernate.transaction.SunONETransactionManagerLookup
INFO: instantiated TransactionManagerLookup
INFO: Automatic flush during beforeCompletion(): disabled
INFO: Automatic session close at end of transaction: disabled
INFO: JDBC batch size: 15
INFO: JDBC batch updates for versioned data: disabled
INFO: Scrollable result sets: enabled
INFO: JDBC3 getGeneratedKeys(): enabled
INFO: Connection release mode: auto
INFO: Maximum outer join fetch depth: 2
INFO: Default batch fetch size: 1
INFO: Generate SQL with comments: disabled
INFO: Order SQL updates by primary key: disabled
INFO: Order SQL inserts for batching: disabled
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
INFO: Using ASTQueryTranslatorFactory
INFO: Query language substitutions: {}
INFO: JPA-QL strict compliance: enabled
INFO: Second-level cache: enabled
INFO: Query cache: disabled
INFO: Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
INFO: Optimize cache for minimal puts: disabled
INFO: Structured second-level cache entries: disabled
INFO: Statistics: disabled
INFO: Deleted entity synthetic identifier rollback: disabled
INFO: Default entity-mode: pojo
INFO: Named query checking : enabled
INFO: Check Nullability in Core (should be disabled when Bean Validation is on): disabled
INFO: building session factory
INFO: Not binding factory to JNDI, no JNDI name configured
INFO: JNDI InitialContext properties:{}
INFO: EJB5181:Portable JNDI names for EJB JpaUserDao: [java:global/YouFood/JpaUserDao, java:global/YouFood/JpaUserDao!com.youfood.dao.UserDao]
INFO: EJB5181:Portable JNDI names for EJB Authenticator: [java:global/YouFood/Authenticator!com.youfood.backoffice.utils.Authenticator, java:global/YouFood/Authenticator]
INFO: WEB0671: Loading application [YouFood] at [/web]
INFO: YouFood a été déployé en 1 279 ms.
Server Log Exception
GRAVE: EJB5070: Exception creating stateless session bean : [Authenticator]
ATTENTION: EJB5184:A system exception occurred during an invocation on EJB Authenticator, method: public com.youfood.backoffice.utils.AuthenticationError com.youfood.backoffice.utils.Authenticator.connect(java.lang.String,java.lang.String) throws java.lang.Exception
ATTENTION: javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:454)
at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2547)
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1899)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at $Proxy150.connect(Unknown Source)
at com.youfood.backoffice.utils.__EJB31_Generated__Authenticator__Intf____Bean__.connect(Unknown Source)
at com.youfood.backoffice.servlet.LoginServlet.doPost(LoginServlet.java:61)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:688)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:680)
Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:726)
at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:247)
at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:449)
... 39 more
Caused by: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:534)
at com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:95)
at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:724)
... 41 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception lors de la tentative d'injection de l'élément Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session dans class com.youfood.backoffice.utils.Authenticator : Lookup failed for 'java:comp/env/com.youfood.backoffice.utils.Authenticator/userDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:703)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:470)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:171)
at com.sun.ejb.containers.BaseContainer.injectEjbInstance(BaseContainer.java:1694)
at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:494)
... 43 more
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/com.youfood.backoffice.utils.Authenticator/userDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' [Root exception is javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:599)
... 47 more
Caused by: javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.youfood.backoffice.utils.Authenticator/userDao,Remote 3.x interface =com.youfood.dao.jpa.JpaUserDao,ejb-link=null,lookup=,mappedName=,jndi-name=com.youfood.dao.jpa.JpaUserDao,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' [Root exception is javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]]
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:191)
at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1109)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:776)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:744)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:169)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:498)
... 51 more
Caused by: javax.naming.NamingException: Lookup failed for 'com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:186)
... 56 more
Caused by: javax.naming.NameNotFoundException: com.youfood.dao.jpa.JpaUserDao#com.youfood.dao.jpa.JpaUserDao not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:248)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:215)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:77)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:119)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:505)
... 60 more
My guess is that you specified names, mapped names and what have you. This is not needed.
Something like the following should work:
EJB:
#Stateless
public class MyBean {
// ...
}
Servlet:
#WebServlet(urlPatterns="/someurl")
public class MyServlet extends HttpServlet {
#EJB
private MyBean myBean;
#Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
}
}
UPDATE:
After seeing your code, the problem is not the injection of the EJB into the Servlet, but the injection of JpaUserDao in Authenticator.
You are injecting it by class, but this will not work since JpaUserDao implements a business interface: UserDao. Because it implements such an interface, there will be no local-view created. As a result, you have to inject using the interface:
#Stateless
public class Authenticator {
private String userFullName;
private Long userId;
#EJB
private UserDao userDao;
// ...
}
As an extra note, the concept of your Authenticator bean is not going to work. It's a stateless bean and its instance variables will have no meaning to the outside world. Thus, getUserFullName() is not guaranteed to return the result you think it will return. It may happen to work momentarily for you in a test when the container happens to select the same bean instance, but this will not work in general.
Even when you hold on to the reference of an Authenticator, it will still not work. The thing is you get a proxy, and the container will potentially direct every call to it to another instance. Think of it as a URL to servers in a web farm where a browser does a call to. You have no guarantee that two successive will go to the exact same physical server.
The authentication that you're trying to do there should be handled by a bean in the web layer and the authentication details put in the HTTP session (additionally, you should maybe use container authentication as well, but that's a whole other thing that's too off-topic here)
There are several ways for injecting a EJB. The most common and simplest solution would be via Dependency Injection as mentioned Arjan Tijms answer.
Another way would be to get a reference via InitialContext.lookup().
In this approach you can choose which lookup name you pass:
Use the class-name of the declaring Bean-Interface:
String jindiName = BeanInterface.class.getName();
InitialContext ctx = new InitialContext();
BeanInterface bi = ctx.lookup(jndiName);
This also works for a remote lookup from any stand-alone client because the interface is public.
Use the JINDI name of the component naming environment:
String jndiName = "java:comp/env/yourejb"
// same as shown above
This will only work inside the same container because the "outside world" do not have access to to the component naming environment.
For a better understanding of jndi names have a look at this.
I hope this helpes, have Fun!
How do I access a Remote EJB component from a stand-alone java client?
Step 1. Use the no-arg InitialContext() constructor in your code.
The most common problem developers run into is passing specific JNDI bootstrapping properties to InitialContext(args). Some other vendors require this step but GlassFish does not. Instead, use the no-arg InitialContext() constructor.
Step 2. Pass the global JNDI name of the Remote EJB to InitialContext.lookup()
Stand-alone java clients do not have access to a component naming environment (java:comp/env) or to the #EJB annotation, so they must explicitly use the global JNDI name to lookup the Remote EJB. (See here for more information on how global JNDI names are assigned to EJB components) Assuming the global JNDI name of the Remote EJB is "FooEJB" :
For Beans with a 3.x Remote Business interface :
Foo foo = (Foo) new InitialContext().lookup("FooEJB");
Note that in the EJB 3.x case the result of the lookup can be directly cast to the remote business interface type without using PortableRemoteObject.narrow().
For EJB 2.1 and earlier session/entity beans :
Object homeObj = new InitialContext().lookup("FooEJB");
FooHome fooHome = (FooHome)
PortableRemoteObject.narrow(homeObj,FooHome.class);
Foo foo = fooHome.create(...)
Step 3. Include the appropriate GlassFish .jars in the java client's classpath.
For GlassFish 3.
Include $GLASSFISH_HOME/glassfish/lib/gf-client.jar in the client's classpath.
E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :
java -classpath $GLASSFISH_HOME/glassfish/lib/gf-client.jar:/home/user1/myclasses acme.MyClient
Note that the Java EE 6 API classes are automatically included by gf-client.jar so there is no need to explicitly add javaee.jar to the classpath. gf-client.jar refers to many other .jars from the GlassFish installation directory so it is best to refer to it from within the installation directory itself rather than copying it(and all the other .jars) to another location.
Note: gf-client.jar is located in $GLASSFISH_HOME/modules/gf-client.jar in GlassFish v3.