0

I have a tomcat application running on AKS. I created bunch of environment variables so when tomcat launches, it can replace the value. When I use printenv in the container, it shows all the environment variables set via deployment.yaml.

However, when tomcat starts, it still doesn't recognizes environment variable, and says something like this:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'PACSDemoController': Invocation of init method failed; nested exception is java.net.URISyntaxException: Illegal character in path at index 1: ${widgetsRestBaseUrl} 

Here is my class:

public class BaseDemoController { protected URI restUri; @Resource(name = "widgetsRestBaseUrl") protected String widgetsRestBaseUrl; @Resource(name = "widgetsServerUploaderUrl") protected String widgetsServerUploaderUrl; @Resource(name = "widgetsServerViewerUrl") protected String widgetsServerViewerUrl; @Resource(name = "widgetsServerStudySelectionUrl") protected String widgetsServerStudySelectionUrl; @Resource(name = "widgetsServerHieStudySelectionUrl") protected String widgetsServerHieStudySelectionUrl; @Resource(name = "widgetsServerPatientHistoryUrl") protected String widgetsServerPatientHistoryUrl; @Resource(name = "widgetsServerShareImageUrl") protected String widgetsServerShareImageUrl; @Resource(name = "widgetServerPacsConfigUrl") protected String widgetServerPacsConfigUrl; @Resource(name = "apiNominate") protected String apiNominate; @Resource(name = "apiPacsConfig") protected String apiPacsConfig; @Resource(name = "widgetsServerNominatePacsUrl") protected String widgetsServerNominatePacsUrl; @Resource(name = "apiBaseUrl") protected String apiBaseUrl; @Resource(name = "widgetsBasicPacsConfigUrl") protected String widgetsBasicPacsConfigUrl; @Resource(name = "auth0Domain") protected String auth0Domain; @Resource(name = "widgetAuth0Audience") protected String widgetAuth0Audience; @Resource(name = "apiAuth0Audience") protected String apiAuth0Audience; @Autowired protected EpicTokenService epicTokenService; @PostConstruct public void initialize() throws URISyntaxException { restUri = new URI(widgetsRestBaseUrl); } 

All of these resources are coming from jndi.xml:

?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"> <bean id="apiBaseUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${apiBaseUrl}"/> </bean> <bean id="widgetsRestBaseUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsRestBaseUrl}"/> </bean> <bean id="widgetsServerUploaderUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerUploaderUrl}"/> </bean> <bean id="widgetsServerViewerUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerViewerUrl}"/> </bean> <bean id="widgetsServerStudySelectionUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerStudySelectionUrl}"/> </bean> <bean id="widgetsServerPatientHistoryUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerPatientHistoryUrl}"/> </bean> <bean id="widgetsServerShareImageUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerShareImageUrl}"/> </bean> <bean id="widgetServerPacsConfigUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetServerPacsConfigUrl}"/> </bean> <bean id="apiPacsConfig" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${apiPacsConfig}"/> </bean> <bean id="apiNominate" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${apiNominate}"/> </bean> <bean id="widgetsServerNominatePacsUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerNominatePacsUrl}"/> </bean> <bean id="widgetsBasicPacsConfigUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsBasicPacsConfigUrl}"/> </bean> <bean id="widgetsServerHieStudySelectionUrl" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetsServerHieStudySelectionUrl}"/> </bean> <bean id="apiAuth0Audience" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${apiAuth0Audience}"/> </bean> <bean id="widgetAuth0Audience" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${widgetAuth0Audience}"/> </bean> <bean id="auth0Domain" class="java.lang.String" factory-method="valueOf"> <constructor-arg value="${auth0Domain}"/> </bean> </beans> 

I am not sure why this is not working. I have two project almost exactly same, and one project works without a problem. Any suggestion?

Update: PACDemoController extends from BaseDemoController:

@Controller public class PACSDemoController extends BaseDemoController { 

and error is coming from @PostConstruct in BaseDemoController. Here is the log:

Caused by: java.net.URISyntaxException: Illegal character in path at index 1: ${widgetsRestBaseUrl} at java.net.URI$Parser.fail(URI.java:2848) at java.net.URI$Parser.checkChars(URI.java:3021) at java.net.URI$Parser.parseHierarchical(URI.java:3105) at java.net.URI$Parser.parse(URI.java:3063) at java.net.URI.<init>(URI.java:588) at com.accelarad.smr.widgets.demo.BaseDemoController.initialize(BaseDemoController.java:90) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ... 27 more 
1
  • The error message says.. Error creating bean with name 'PACSDemoController' Please include the code for the PACSDemoController class Commented May 18, 2021 at 21:28

1 Answer 1

3

Tomcat doesn't have anything to do with the replacement of ${...} with the value of the corresponding system environment variable. It only replaces those values in its own configuration files (server.xml, various context.xml descriptors, etc.).

If you want Spring to replace those property placeholders ${...}, you need to add a PropertySourcesPlaceholderConfigurer to your application context. This can be done through:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder /> ... </beans> 

However it is much easier to inject the property values directly from the Spring Environment using the @Value annotation instead of creating hundreds of beans of type java.lang.String.

Sign up to request clarification or add additional context in comments.

3 Comments

You are right that tomcat is not responsible for replacement. However, I do have this in my pom.xml. I also have PropertySourcesPlaceholderConfigurer class coming from spring. <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.13.RELEASE</version> </dependency>
Thanks! I missed <context:property-placeholder /> part. I added it to context.xml and it works. I am pretty sure it will work if I add it to jndi.xml as well.
You didn't explain what jndi.xml and context.xml are (these are note default Spring names), but I assume that context.xml imports jndi.xml so it should work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.