User session not found if 2nd thread is running

So i’m not sure what’s going wrong, but suppose I want to call a service without any user being logged in. I set up my thread in a AppLifeCycle/AppContext. The thread runs on application start and calls another service to monitor a directory for any changes, then does something depending on the change.
When I try to run this ( change a file in the directory), an error occurs : User Session is not found. I understand that it might be due to having no user in the thread.
How could I make sure the thread runs regardless of user logged in or not?

I suppose you create your startup logic on the middle tier (core module). Then you can invoke regular managed beans instead of services. Services are designed to be called from clients and require presence of a user session in the thread. Managed beans have no such restriction, however you still need to authenticate when saving data to the database. It can be easily done using Authentication bean.

If you need to propagate authentication to new threads from code already having a user session, use SecurityContext.

1 Like

Hello,
It seems that this would solve my issue, but the problem is that adding the authentication bean (@Authenticated) to the bean method isn’t allowing me to use EntityManager in the method.
Here’s a part of what I’m doing:
In ImportClass:

@Service(ImportService.NAME) 
public class ImportServiceBean implements ImportService { 
   @Authenticated 
    @Override 
    public void importItemsData(List<Map<String, String>> data){ 
        Persistence persistence = AppBeans.get(Persistence.class); 
        try (Transaction transaction = persistence.createTransaction()) { 
            EntityManager entityManager = persistence.getEntityManager(); 
            TypedQuery<ImportSettings> query = entityManager.createQuery("select e from company$ImportSettings e", ImportSettings.class); 
            query.setView(ImportSettings.class, "_local"); 
            List<ImportSettings> importSettings = query.getResultList(); 
            Map<String, Order> orderMap = new HashMap<>(); 
            Map<String, Bundle> bundleMap = new HashMap<>(); 
            Map<String, Item> itemMap = new HashMap<>(); 
            Metadata metadata = AppBeans.get(Metadata.class); 
            for (int i = 0; i < data.size(); i++) { 
                Map<String, String> currentRow = data.get(i); 
                Order addedOrder = metadata.create(Order.class); 
                Bundle addedBundle = metadata.create(Bundle.class); 
                Item addedItem = metadata.create(Item.class); 
                for (ImportSettings importSetting : importSettings) { 
                    String currentRowHeader = importSetting.getLocalFieldName(); 
                    String currentRowData = currentRow.get(currentRowHeader); 
                    switch (currentRowHeader) { 
                        case "orderNumber": 
                            addedOrder.setNumber(currentRowData); 
                            break; 
                        case "orderStatus": 
                            addedOrder.setStatus(currentRowData); 
                            break; 
                        case "epc": 
                            addedItem.setEpc(currentRowData); 
                            break; 
                        case "barcode": 
                            addedItem.setBarcode(currentRowData); 
                            break; 
                        case "bundleNumber": 
                            addedBundle.setNumber(currentRowData); 
                            break; 
                        case "bundleEPC": 
                            addedBundle.setEpc(currentRowData); 
                            break; 
                        case "bundleBarcode": 
                            addedBundle.setBarcode(currentRowData); 
                            break; 
                    } 
                } 
                if (!orderMap.containsKey(addedOrder.getNumber())) { 
                    addedOrder.setBundles(new HashSet<>()); 
                    orderMap.put(addedOrder.getNumber(), addedOrder); 
                    entityManager.persist(addedOrder);                                        //ANY entity manager calls then requires a user session 
                } 
                if (!bundleMap.containsKey(addedBundle.getNumber())) { 
                    addedBundle.setItems(new HashSet<>()); 
                    bundleMap.put(addedBundle.getNumber(), addedBundle); 
                    entityManager.persist(addedBundle); 
                } 
                if (!itemMap.containsKey(addedItem.getEpc())) { 
                    itemMap.put(addedItem.getEpc(), addedItem); 
                    entityManager.persist(addedItem); 
                } 
                Order order = orderMap.get(addedOrder.getNumber()); 
                Bundle bundle = bundleMap.get(addedBundle.getNumber()); 
                Item item = itemMap.get(addedItem.getEpc()); 
                order.getBundles().add(bundle); 
               entityManager.merge(order);                                 
                bundle.getItems().add(item); 
                bundle.setOrder(order); 
                entityManager.merge(bundle); 
                item.setBundle(bundle); 
              entityManager.merge(item); 
            } 
            transaction.commit(); 
        } 
} 

Thanks for your help

Are you trying to invoke importItemsData() from a new thread started from AppContext.Listener? Then ServiceInterceptor does not allow you to enter the method because your call has no authentication information.

Use a regular managed bean instead of the service, then the @Authenticated annotation should work because there will be no ServiceInterceptor that prevents the call.

If it doesn’t help, provide the code that calls the method and stacktrace of an exception that you get.