I am working on a micro service based on spring boot
Now i have two services
configserver
discoveryserver
coreservice
I can able to start configserver and coreserver.Both are working fine.coreserver taking configuration from configserver. All properties are save on my file system as an application properties
configurations
when i run my discoveryserver it showing below error
20:52:34.918 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalStateException: Unable to load config data from 'configserver:'
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:141)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:126)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:119)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.lambda$resolve$1(ConfigDataLocationResolvers.java:115)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:126)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:115)
at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:107)
at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:105)
at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:97)
at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:85)
at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
at org.springframework.boot.context.config.ConfigDataEnvironment.processInitial(ConfigDataEnvironment.java:240)
at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:227)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:344)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
at com.nielsen.discoveryserver.DiscoveryServerApplication.main(DiscoveryServerApplication.java:12)
Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader. If the location is meant to reference a directory, it must end in '/' or File.separator
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferencesForFile(StandardConfigDataLocationResolver.java:229)
at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:138)
... 31 common frames omitted
Process finished with exit code 1
discovery server application.properties
spring.cloud.config.uri= http://localhost:8888
spring.application.name = discoveryserver
spring.config.import = configserver:
spring.profiles.active= native
configuration repository properties named same as application name
discoveryserver.properties
server.port =8081
mian class
#SpringBootApplication
#EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}
coreserver have the similar configurations.its working file for me.i coudn't understand why discoveryserver throwing error.
Help on this issue.
Thanks in advance.
Related
We are using Spring Cloud Config Server to provide the environment for our Project.
However in order to deploy it I have to embed it into the main Spring application.
I followed the documentation on how to run the Cloud Config as an embedded server, which means I added the #EnableConfigServer annotation in the main java file, as well as setting spring.cloud.config.server.bootstrap to true.
According to the documentation i created the required bootstrap.yml which looks something like this.
---
spring:
application:
name: application
cloud:
config:
label: main
fail-fast: true
server:
composite:
-
type: git
uri: # HTTPS link to Repo
clone-on-start: true
default-label: main
git:
clone-on-start: true
default-label: main
bootstrap: true
However when I try to start the Server it always crashes with the following error: java.lang.IllegalStateException: Error processing condition on org.springframework.cloud.config.server.config.CompositeRepositoryConfiguration.searchPathCompositeEnvironmentRepository.
When I remove the #EnableConfigServer annotation this error does not appear, but the Server crashes anyway because it obviously does not load any configuration anymore.
I read that this problem may have something to do with the Spring Boot and Spring Cloud version in use, but I have attempted it with multiple versions.
Currently im on Spring Boot 2.6.3 and Spring Cloud 2021.0.1 which implicitly gives me a spring-cloud-config-server of version 3.1.1
Is there any way to get the embedded Config server working?
Update:
Full Trace:
java.lang.IllegalStateException: Error processing condition on org.springframework.cloud.config.server.config.CompositeRepositoryConfiguration.searchPathCompositeEnvironmentRepository
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-2.6.3.jar:2.6.3]
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:193) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:153) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.15.jar:5.3.15]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:414) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.6.3.jar:2.6.3]
at ServerApplication.main(ServerApplication.java:27) ~[classes/:na]
Caused by: java.util.NoSuchElementException: No value bound
at org.springframework.boot.context.properties.bind.BindResult.get(BindResult.java:55) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.cloud.config.server.composite.CompositeUtils.getCompositeTypeList(CompositeUtils.java:51) ~[spring-cloud-config-server-3.1.1.jar:3.1.1]
at org.springframework.cloud.config.server.composite.OnSearchPathLocatorPresent.getMatchOutcome(OnSearchPathLocatorPresent.java:40) ~[spring-cloud-config-server-3.1.1.jar:3.1.1]
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.6.3.jar:2.6.3]
... 17 common frames omitted
Process finished with exit code 1
application.yml
---
spring:
cloud:
config:
server:
bootstrap: true
required usernames and passwords are provided via environment variables
ServerApplication.java (main file)
#SpringBootApplication
#EnableConfigServer
#EnableScheduling
#EnableSchedulerLock(defaultLockAtMostFor = "PT5M", interceptMode = EnableSchedulerLock.InterceptMode.PROXY_SCHEDULER, mode = AdviceMode.PROXY)
#EnableAsync
#EnableCaching
#EnableTransactionManagement
public class ServerApplication {
public static void main(String[] args) {
SpringApplication.run(ServerApplication.class, args);
}
#Bean
public LockProvider lockProvider(DataSource dataSource) {
return new JdbcTemplateLockProvider(dataSource);
}
}
Update 2
I made some progress in fixing the error.
It came from the active profiles i set (as an env variable). I used "dev" and "composite" even though only the composite profile has been defined in bootstrap.yml
However the application is still crashing on startup because the cloud config server does work
Update 3
I fixed the problems by adding the following dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
I am in the process of upgrading a Spring Boot application to support Micrometer and Actuator monitoring. I have upgraded the Spring libraries to newer versions, and I have refactored the code accordingly (you can see before and after code samples later in in this question). I could run the application successfully before; when I try to do so now, I am getting the following error message:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-08-20 14:14:59.302 ERROR 29703 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.9.jar:5.3.9]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:143) [spring-boot-2.5.3.jar:2.5.3]
at com.openbet.realitycheck.Application.main(Application.java:22) [classes/:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:210) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:180) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.5.3.jar:2.5.3]
... 7 common frames omitted
The below screenshot describes the library versions that were previously used:
enter image description here
These are the upgraded libraries that I am using now:
enter image description here
Some before-and-after code samples:
Before:
#SpringApplicationConfiguration(classes = {Application.class, IntegrationTestConfiguration.class})
#WebIntegrationTest("server.port=0")
After:
#SpringBootTest(classes = {Application.class, IntegrationTestConfiguration.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Before:
#SpringApplicationConfiguration(classes = UnitTestConfiguration.class)
After:
#SpringBootTest(classes = UnitTestConfiguration.class)
Here is my starter class:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
// Change the default config name to xxxxxxxxxxxx.
new SpringApplicationBuilder(Application.class)
.properties(Collections.singletonMap("spring.config.name", "xxxxxxxxxxxx"))
.run(args);
}
}
When I specify that this is not a Web Application...
#SpringBootApplication
public class Application {
public static void main(String[] args) {
// Change the default config name to xxxxxxxxxxxx.
new SpringApplicationBuilder(Application.class)
.web(WebApplicationType.NONE)
.properties(Collections.singletonMap("spring.config.name", "xxxxxxxxxxxx"))
.run(args);
}
}
...I receive a different set of error messages:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field customerPrefRepository in com.corpname.appname.core.services.CustomerPrefServiceImpl required a bean of type 'com.corpname.appname.core.repositories.CustomerPrefRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.corpname.appname.core.repositories.CustomerPrefRepository' in your configuration.
As this is a web-based application, I don't know of how much use this last bit for information would be.
I'm trying out kotlin and spring boot with spring data.
id("org.springframework.boot") version "2.1.8.RELEASE"
I have some schema-*.sql files in src/main/resources. I put this in my application.properties
spring.datasource.schema=/sql/schema-*.sql
I then made a small spring boot ApplicationRunner-based app (so set WebApplicationType.NONE) and these all get executed as expected and the app starts fine.
#SpringBootApplication
private class MainApp(): ApplicationRunner { ... }
fun main(args: Array<String>) {
runApplication<MainApp>(*args) {
webApplicationType = WebApplicationType.NONE
}
}
Now, when I change the above to WebApplicationType.SERVLET, I get the following:
Caused by: java.io.FileNotFoundException: ServletContext resource [/sql/] cannot be resolved to URL because it does not exist
at org.springframework.web.context.support.ServletContextResource.getURL(ServletContextResource.java:173) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:498) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:298) ~[spring-core-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.boot.devtools.restart.ClassLoaderFilesResourcePatternResolver.getResources(ClassLoaderFilesResourcePatternResolver.java:109) ~[spring-boot-devtools-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.context.support.GenericApplicationContext.getResources(GenericApplicationContext.java:233) ~[spring-context-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.config.SortedResourcesFactoryBean.createInstance(SortedResourcesFactoryBean.java:76) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.jdbc.config.SortedResourcesFactoryBean.createInstance(SortedResourcesFactoryBean.java:42) ~[spring-jdbc-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:142) ~[spring-beans-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.doGetResources(DataSourceInitializer.java:175) ~[spring-boot-autoconfigure-2.1.8.RELEASE.jar:2.1.8.RELEASE]
... 89 common frames omitted
This exception goes away and the http server seems to be fine when I omment out:
spring.datasource.schema=/sql/schema-*.sql
Any ideas what I'm supposed to change to make this work?
Try that spring.datasource.schema=classpath:sql/schema-*.sql.
I have an application that works just fine as war in tomcat. Now I would like to start it from Embedded Tomcat using such code:
public static void main(String[] args) throws Exception {
Tomcat tomcat = new Tomcat();
tomcat.enableNaming();
StandardContext ctx =
(StandardContext) tomcat.addWebapp("/myapp", new File("src/main/webapp/").getAbsolutePath());
StandardJarScanner jarScanner = (StandardJarScanner) ctx.getJarScanner();
jarScanner.setScanClassPath(false);
jarScanner.setScanAllDirectories(false);
jarScanner.setScanBootstrapClassPath(false);
tomcat.start();
tomcat.getServer().await();
}
Application seams to be starting but after loading of few Spring Services it gets such Exception
Caused by: java.lang.IllegalAccessError: class de.abc.service.intern.$Proxy213 cannot access its superinterface de.abc.service.intern.PageMetadataStorage
at java.lang.reflect.Proxy.defineClass0(Native Method)
at java.lang.reflect.Proxy.access$300(Proxy.java:228)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:642)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557)
at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230)
at java.lang.reflect.WeakCache.get(WeakCache.java:127)
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719)
at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:122)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
Looks like $Proxy213 got loaded by bootstrap class loader and cannot access class from web app. And problematic interface is package protected.
Could some one explain what is happening here? Could I solve it somehow?
#Configuration
#EnableAutoConfiguration
#ComponentScan
#SpringBootApplication
public class InitService extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run("classpath:abc-server.xml", args);
}
}
++++++++++++++++++++++++++++++++++++++++++
Here i am trying to migrate the Spring MVC project to Spring boot Standalone jar with embedded tomcat. So i tried loading the context xml(abc-server.xml) used in the existing project. When i run/deploy the spring boot jar, the following exception is thrown.
++++++++++++++++++++++++++++++++++++
[2015-05-19 15:12:30,012] ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
at com.gogo.asp.server.init.InitService.main(InitService.java:188)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
... 13 more
When you call run, you're only providing server-abc.xml as a source for your application's configuration:
SpringApplication.run("classpath:abc-server.xml", args);
That means that InitService is being ignored, including the fact that you've enabled auto-configuration. Without auto-configuration being switched on, Spring Boot will not automatically configure an embedded servlet container for you. You need to provide both InitService and abc-server.xml as configuration for your application.
I would provide InitService.class to SpringApplication.run and use #ImportResource to pull in your old XML configuration:
#SpringBootApplication
#ImportResource("classpath:abc-server.xml")
public class InitService {
public static void main(String[] args) {
SpringApplication.run(InitService.class, args);
}
}
Note that #SpringBootApplication is equivalent to #ComponentScan, #Configuration, and #EnableAutoConfiguration. You can just use #SpringBootApplication and drop the other three annotations as I've done above.