Module development: org.openmrs.api.APIException: Service not found

Hi,

I’m creating a new module for CSV imports and trying to test it on a static main() method. I’m stuck with an exception. I get org.openmrs.api.APIException: Service not found exception whenever I try Context.getService(CsvImporterService.class);

My moduleApplication-context.xml has this bean, but I still get the following:

log4j:WARN No appenders could be found for logger (org.openmrs.util.OpenmrsUtil).
log4j:WARN Please initialize the log4j system properly.
INFO 4/25/15 1:05 PM:liquibase: Reading from `liquibasechangelog`
WARNING 4/25/15 1:05 PM:liquibase: modifyDataType will lose primary key/autoincrement/not null settings for mysql.  Use <sql> and re-specify all configuration if this is the case
INFO 4/25/15 1:05 PM:liquibase: liquibase.xml is using schema version 1.9 rather than version 2.0
INFO 4/25/15 1:05 PM:liquibase: Reading from `liquibasechangelog`
INFO 4/25/15 1:06 PM:liquibase: Successfully acquired change log lock
INFO 4/25/15 1:06 PM:liquibase: liquibase.xml is using schema version 1.9 rather than version 2.0
INFO 4/25/15 1:06 PM:liquibase: Successfully released change log lock
Exception in thread "main" org.openmrs.api.APIException: Service not found: interface org.openmrs.module.csvimporter.CsvImporterService
	at org.openmrs.api.context.ServiceContext.getService(ServiceContext.java:727)
	at org.openmrs.api.context.Context.getService(Context.java:914)
	at org.openmrs.module.csvimporter.CsvImporterMain.main(CsvImporterMain.java:70)

Can somebody suggest me where I’m wrong? Btw, I’m launching this as Java Application from class CsvImporterMain.java

Greetings! Is the CsvImporterService a service that you have defined in your module? If so, did you create the bean definition to your service in the moduleApplicationContext.xml file?

Thanks for responding Wesley, yes it’s a service and I’ve defined following bean in moduleApplicationContext.xml

<bean parent="serviceContext">
		<property name="moduleService">
			<list>
				<!-- service interface name. this is the "key" to look up our service 
					in Context.getService() -->
				<value>org.openmrs.module.csvimporter.CsvImporterService</value>
				<bean
					class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
					<property name="transactionManager">
						<ref bean="transactionManager" />
					</property>
					<property name="target">
						<!-- This is our service class implementation that actually does the 
							business logic -->
						<bean class="org.openmrs.module.csvimporter.impl.CsvImporterServiceImpl">

							<!-- this calls csvImporterServiceImpl.setDao(new CsvImporterDAOImpl) -->
							<property name="dao">
								<bean
									class="org.openmrs.module.csvimporter.db.hibernate.CsvImporterDAOImpl">

									<!-- the "sessionFactory" object is provided by the applicationContext-service.xml 
										file in core openmrs -->
									<property name="sessionFactory">
										<ref bean="sessionFactory" />
									</property>
								</bean>
							</property>
						</bean>
					</property>

					<property name="preInterceptors">
						<!-- This is a list of AOP advice that wraps around each of the methods 
							in our CsvImporterServiceImpl -->
						<ref bean="serviceInterceptors" />
					</property>
					<property name="transactionAttributeSource">
						<bean
							class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" />
					</property>
				</bean>
			</list>
		</property>
	</bean>

Sorry… after reading your message more closely I see that you already mentioned about the moduleApplicationContext file.

Is the exception stack trace that you copied all that was logged? Also, It looks like you are attempting to get an instance of the service from a ‘main’ method. I assume that you’re trying to get this service instance when your module is starting up, is that correct? If so, you might want to try moving whatever logic you’ve got in main into your ModuleActivator class, in the appropriate method (ie, started). I wonder if your call is happening before everything is properly set up in OpenMRS and before your module services have been added to the OpenMRS services.

Hope that helps!

Yes, you’re right. I’m trying this out in a main function. But my understanding is that when you call Context.startup(), that is where everything is set up properly. Here is what I’m trying:

try { Properties props = OpenmrsUtil.getRuntimeProperties(“openmrs”); String url = (String) props.get(“connection.url”); String username = (String) props.get(“connection.username”); String password = (String) props.get(“connection.password”); Context.startup(url, username, password, props); Context.openSession(); Context.authenticate(“owais”, “Jingle94$”); importerService = Context.getService(CsvImporterService.class); } catch (Exception e) { e.printStackTrace(); }

Did you put your module in the modules folder? Or did you supply your module’s path and file name in the runtime properties file via the key named “module.list_to_load”?

Thanks for the response Daniel. I’m not exporting the module yet. I’m just trying to run it as a Java Application.

I was about to ask if you have checked that your module is started, but your last message implies your have not actually installed the module, you need to build the module and add it to the module repo in order to use its services.

This could be caused by the applicationContext file looking into a wrong project/(maven)module say for-example when your test is placed in api yet your moduleApplicationContext.xml may be in omod.

You can choose to take one of these three approaches to resolve this:

  1. Move the moduleApplicationContext.xml file to the project/(maven)module where you have the test such as: api/src/main/resources/ if your test in under api
  2. Move your test to the project/(maven)module where your moduleApplicationContext.xml
  3. Separate your moduleApplicationContext.xml into two application context files one in api and the other in omod such that the paths to each of them as; api/src/main/resources/moduleApplicationContext.xml omod/src/main/resources/webModuleApplicationContext.xml one in api project/(maven)module contains service/api specific bean definitions only where as the other contains the rest. Examples can be found at:

I prefer the last or third one :smile: this way paths are righted

2 Likes

Hello,

I am getting the same error - org.openmrs.api.APIException: Service not found Scenario - I am developing 2 interconnected modules - Drug Order and Pharmacy The Pharmacy module calls the service defined in Drug Order module

Context.getService(drugordersService.class).getDrugOrderByOrderID(order.getOrderId());

Initially, when I install the Pharmacy module - I get it right. i.e I am able to fetch the Drug Order I need. However, when I go back to the Drug Order page, I see the error. Subsequently, I find that just one of the modules work at a time while the other fails to load.

Here are the logs - http://pastebin.com/T6b2U0MW

Could you please suggest a way I can fetch the records from my “drugorder_extension” table that I define in my drugorders module - in my pharmacy module… Thank you!

How does your DrugordersFragmentController class look like. How about your moduleApplicationContext.xml file?

This is the moduleApplicationContext file of my Pharmacy module

My DrugordersFragmentController refers to the fragment on the Patient dashboard which displays the list of DrugOrders

I mean for the drug orders module.

Thanks for the reply, here is the link to the moduleApplication file of the Drug Order Module

Can we also look at your drug order service java file?

In the pharmacy module, add scope provided to the drug orders dependency.

1 Like

Thank you!! That fixed it!