- Build System (maven)
- Application framework (spring boot)
- Database (MySQL, Cassandra)
- CI/CD (Jenkins)
- Deployment (internal, private cloud built on OS tech such as K8S or PCF (cloudfoundry))
An enterprise Java application typically looks like a "jar" (compiled java, Java ARchive)
MyClass.java => MyClass.class => MyApplication.jar
java -jar MyApplication.jar
=> start your web server, start listening for HTTP requests
Your application has a bunch of dependencies. Similar to Node's package.json, maven has a pom.xml that encodes all required dependecies.
<project>
<name>ryan-todo-service</name>
<dependencies>
<dependency>
<group>org.springframework</group>
<artifact>spring-boot-starter<artifact>
<version>2.2.5-RELEASE</version>
</dependency>
</dependencies>
<build>
</build>
</project>
Java is a compiled language. Meaning, the code you right != the code that runs. Your code is translated into bytecode, and then your bytecode runs on the JVM.:w
JDK => translator from *.java to *.class (handled by javac
)
Maven => collector of all *.class into a MyApplication.jar (handled by mvn
cli)
JRE => Java Runtime Environment, virtual machine that runs your code (handled by the java
command)
Creates "spring context"
Runs all configuration classes
Runs your Spring Application (starts listening on endpoints, typically using an embedded server)
There are certain "resources" that your entire application requires. Spring makes those resources available to different classes in your application via "dependency injection."
It supplies all resources required by a given class from the "Spring context." For a class to be able to get access to a resource, that resource must be present in the spring context and must be specific enough.
These resources are called "Beans" in the spring ecosystem.
The process of making these "beans" available to your different classes (called "spring components" in the spring ecosystem) is called "autowiring."
So, Spring starts its lifecycle by autowiring all beans to the components that depend on them.
Autowiring == dependency injection
Beans == resource in the spring context that a class depends on
Component == class that exists in the spring ecosystem
Spring is all about opinions. It has a very clear framework for you to write your code in, so you dont have to go crazy trying to find the BEST way to do a certain thing. Usually, there is only one way.
One of the strongest opinions it has is about configuration. As much of your application as possible should be encoded in readable configuration.
Use case: todos.
You wish to set an application-wide limit on how many todos can be created. In node, you could do this from an environment variable OR a constant in your code OR a mutable thing that you can change from your API.
But in spring, we would set a configuration entry for that constant, and we always know where that configuration is. Other such configuration includes database URLs, API URLs, the port you want to expose something on, etc.
This configuration is stored in the src/main/resources
directory, in a file called application.yml
.
Spring uses Annotations / decorators to make shit a lot easier for you.
Inspiration for this: java sucks, extremely verbose.
Also, lombok provides a lot of good ones for interacting with POJOs
In enterprise applications, most companies will leverage centralized logging infrastructure. This is typically deployed on the ELK stack (Elasticsearch, Logstash, Kibana).
Elasticsearch => highly indexed, fast DB for maximizing speed of search for large amts of text Logstash => agent that runs wherever your application runs, and ships all the logs to Elasticsearch Kibana => Frontend to view and search logs from.
Logs must conform to a pre-defined GROK pattern to be able to be indexed properly by elasticsearch. The way we conform our logs to that pattern is by using a centralized logging framework.
In Java, the most popular logging framework is called log4j. Another one is logback.
Though you can use any of those frameworks, you don't want to be tied down to a logging framework. SO we use a logging-framework-api, which all log frameworks have to conform to. This api (not a rest API) is called Slf4j.
Slf4j can sit on top of any logging framework like log4j or logback and give you a single way to interact with them.
log.info log.debug log.warn
Lombok offers an @Slf4j annotation, which injects a log
into your class that you can use in any method to print stuff.