├── .github └── workflows │ ├── build.yaml │ ├── compatibility.yaml │ ├── docs.yaml │ └── release.yaml ├── .gitignore ├── .mvn ├── jvm.config └── wrapper │ └── maven-wrapper.properties ├── CODE_OF_CONDUCT.adoc ├── LICENSE ├── README.adoc ├── application.yml ├── etc ├── backport-ticket.sh ├── ide │ ├── eclipse-formatting.xml │ └── intellij-formatting.jar ├── mappings.txt ├── migrate-to-1.0.sh ├── release.adoc └── update-dependencies.sh ├── lombok.config ├── mvnw ├── mvnw.cmd ├── pom.xml ├── settings.xml └── src ├── docs ├── java │ └── org │ │ └── springframework │ │ └── hateoas │ │ ├── AffordancesSample.java │ │ ├── CollectionJsonApplication.java │ │ ├── EmployeeController.java │ │ ├── EmployeeModel.java │ │ ├── ForwardedEnabledConfig.java │ │ ├── FundamentalsTest.java │ │ ├── HalFormsApplication.java │ │ ├── PaymentProcessingApp.java │ │ ├── PaymentProcessor.java │ │ ├── SampleAppConfiguration.java │ │ ├── UberApplication.java │ │ ├── client │ │ └── HypermediaConfiguration.java │ │ ├── mediatype │ │ └── problem │ │ │ ├── PaymentController.java │ │ │ ├── PaymentResult.java │ │ │ └── PaymentService.java │ │ └── support │ │ ├── Customer.java │ │ ├── Order.java │ │ ├── Payment.java │ │ └── PaymentController.java └── resources │ ├── assemblies │ └── docs.xml │ └── org │ └── springframework │ └── hateoas │ └── docs │ ├── mediatype │ ├── collectionjson │ │ ├── spec-part1.json │ │ ├── spec-part2.json │ │ ├── spec-part3.json │ │ ├── spec-part4.json │ │ ├── spec-part5.json │ │ ├── spec-part6.json │ │ └── spec-part7.json │ ├── hal │ │ ├── forms │ │ │ ├── hal-forms-sample-with-notes.json │ │ │ └── hal-forms-sample.json │ │ ├── hal-multiple-entry-link-relation.json │ │ ├── hal-single-entry-link-relation-array.json │ │ ├── hal-single-entry-link-relation-object.json │ │ └── hal-with-curies.json │ ├── problem │ │ └── response.json │ └── uber │ │ └── uber-sample.json │ ├── order-plain.json │ └── order-with-payment-link.json ├── main ├── asciidoc │ ├── client.adoc │ ├── configuration.adoc │ ├── fundamentals.adoc │ ├── index.adoc │ ├── mediatypes.adoc │ ├── migrate-to-1.0.adoc │ └── server.adoc ├── java │ └── org │ │ └── springframework │ │ └── hateoas │ │ ├── Affordance.java │ │ ├── AffordanceModel.java │ │ ├── CollectionModel.java │ │ ├── EntityModel.java │ │ ├── IanaLinkRelations.java │ │ ├── IanaUriSchemes.java │ │ ├── InputType.java │ │ ├── Link.java │ │ ├── LinkParser.java │ │ ├── LinkRelation.java │ │ ├── Links.java │ │ ├── MediaTypes.java │ │ ├── NonComposite.java │ │ ├── PagedModel.java │ │ ├── QueryParameter.java │ │ ├── RepresentationModel.java │ │ ├── SlicedModel.java │ │ ├── StringLinkRelation.java │ │ ├── TemplateVariable.java │ │ ├── TemplateVariables.java │ │ ├── UriTemplate.java │ │ ├── aot │ │ ├── AotUtils.java │ │ ├── ControllerMethodReturnTypeAotProcessor.java │ │ ├── HateoasTypesRuntimeHints.java │ │ ├── HypermediaTypeAotProcessor.java │ │ ├── HypermediaTypesRuntimeHints.java │ │ ├── RepresentationModelAssemblerAotProcessor.java │ │ └── package-info.java │ │ ├── client │ │ ├── Hop.java │ │ ├── JsonPathLinkDiscoverer.java │ │ ├── LinkDiscoverer.java │ │ ├── LinkDiscoverers.java │ │ ├── Rels.java │ │ ├── Traverson.java │ │ ├── TraversonDefaults.java │ │ └── package-info.java │ │ ├── config │ │ ├── EnableHypermediaSupport.java │ │ ├── EntityLinksConfiguration.java │ │ ├── HateoasConfiguration.java │ │ ├── HypermediaConfigurationImportSelector.java │ │ ├── HypermediaMappingInformation.java │ │ ├── HypermediaMappingInformationComparator.java │ │ ├── HypermediaRestTemplateConfigurer.java │ │ ├── HypermediaWebClientConfigurer.java │ │ ├── HypermediaWebTestClientConfigurer.java │ │ ├── MediaTypeConfigurationProvider.java │ │ ├── RestTemplateHateoasConfiguration.java │ │ ├── WebClientHateoasConfiguration.java │ │ ├── WebConverters.java │ │ ├── WebFluxHateoasConfiguration.java │ │ ├── WebMvcEntityLinksConfiguration.java │ │ ├── WebMvcHateoasConfiguration.java │ │ ├── WebStackImportSelector.java │ │ ├── WebTestHateoasConfiguration.java │ │ ├── WebfluxCodecCustomizer.java │ │ └── package-info.java │ │ ├── mediatype │ │ ├── AffordanceModelFactory.java │ │ ├── AffordanceOperations.java │ │ ├── Affordances.java │ │ ├── ConfigurableAffordance.java │ │ ├── ConfigurableHandlerInstantiator.java │ │ ├── ConfiguredAffordance.java │ │ ├── DefaultOnlyMessageResolver.java │ │ ├── InputTypeFactory.java │ │ ├── JacksonHelper.java │ │ ├── MediaTypeConfigurationCustomizer.java │ │ ├── MediaTypeConfigurationFactory.java │ │ ├── MessageResolver.java │ │ ├── MessageSourceResolvableSerializer.java │ │ ├── MessageSourceResolver.java │ │ ├── PropertyUtils.java │ │ ├── TypeBasedPayloadMetadata.java │ │ ├── alps │ │ │ ├── Alps.java │ │ │ ├── AlpsLinkDiscoverer.java │ │ │ ├── Descriptor.java │ │ │ ├── Doc.java │ │ │ ├── Ext.java │ │ │ ├── Format.java │ │ │ ├── Type.java │ │ │ └── package-info.java │ │ ├── collectionjson │ │ │ ├── CollectionJson.java │ │ │ ├── CollectionJsonAffordanceModel.java │ │ │ ├── CollectionJsonAffordanceModelFactory.java │ │ │ ├── CollectionJsonData.java │ │ │ ├── CollectionJsonDocument.java │ │ │ ├── CollectionJsonError.java │ │ │ ├── CollectionJsonItem.java │ │ │ ├── CollectionJsonLinkDiscoverer.java │ │ │ ├── CollectionJsonMediaTypeConfiguration.java │ │ │ ├── CollectionJsonMediaTypeConfigurationProvider.java │ │ │ ├── CollectionJsonQuery.java │ │ │ ├── CollectionJsonTemplate.java │ │ │ ├── CollectionRepresentationModelMixin.java │ │ │ ├── EntityRepresentationModelMixin.java │ │ │ ├── Jackson2CollectionJsonModule.java │ │ │ ├── PagedResourcesMixin.java │ │ │ ├── RepresentationModelMixin.java │ │ │ └── package-info.java │ │ ├── hal │ │ │ ├── CollectionModelMixin.java │ │ │ ├── CurieProvider.java │ │ │ ├── DefaultCurieProvider.java │ │ │ ├── HalConfiguration.java │ │ │ ├── HalEmbeddedBuilder.java │ │ │ ├── HalLinkDiscoverer.java │ │ │ ├── HalLinkRelation.java │ │ │ ├── HalMediaTypeConfiguration.java │ │ │ ├── HalMediaTypeConfigurationProvider.java │ │ │ ├── HalModelBuilder.java │ │ │ ├── HalTraversonDefaults.java │ │ │ ├── Jackson2HalModule.java │ │ │ ├── LinkMixin.java │ │ │ ├── RepresentationModelMixin.java │ │ │ ├── forms │ │ │ │ ├── HalFormsAffordanceModel.java │ │ │ │ ├── HalFormsAffordanceModelFactory.java │ │ │ │ ├── HalFormsConfiguration.java │ │ │ │ ├── HalFormsDeserializers.java │ │ │ │ ├── HalFormsHttpMessageConverter.java │ │ │ │ ├── HalFormsLinkDiscoverer.java │ │ │ │ ├── HalFormsMediaTypeConfiguration.java │ │ │ │ ├── HalFormsMediaTypeConfigurationProvider.java │ │ │ │ ├── HalFormsOptions.java │ │ │ │ ├── HalFormsOptionsFactory.java │ │ │ │ ├── HalFormsPromptedValue.java │ │ │ │ ├── HalFormsProperty.java │ │ │ │ ├── HalFormsPropertyFactory.java │ │ │ │ ├── HalFormsTemplate.java │ │ │ │ ├── HalFormsTemplateBuilder.java │ │ │ │ ├── HalFormsTemplatePropertyWriter.java │ │ │ │ ├── Jackson2HalFormsModule.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ ├── html │ │ │ ├── HtmlInputType.java │ │ │ ├── HtmlInputTypeFactory.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── problem │ │ │ ├── HttpProblemDetailsConfigurationProvider.java │ │ │ ├── HttpProblemDetailsMappingInformation.java │ │ │ ├── Problem.java │ │ │ └── package-info.java │ │ └── uber │ │ │ ├── Jackson2UberModule.java │ │ │ ├── Uber.java │ │ │ ├── UberAction.java │ │ │ ├── UberAffordanceModel.java │ │ │ ├── UberAffordanceModelFactory.java │ │ │ ├── UberData.java │ │ │ ├── UberDocument.java │ │ │ ├── UberError.java │ │ │ ├── UberLinkDiscoverer.java │ │ │ ├── UberMediaTypeConfiguration.java │ │ │ ├── UberMediaTypeConfigurationProvider.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── server │ │ ├── EntityLinks.java │ │ ├── ExposesResourceFor.java │ │ ├── LinkBuilder.java │ │ ├── LinkBuilderFactory.java │ │ ├── LinkRelationProvider.java │ │ ├── MethodLinkBuilderFactory.java │ │ ├── RepresentationModelAssembler.java │ │ ├── RepresentationModelProcessor.java │ │ ├── SimpleRepresentationModelAssembler.java │ │ ├── TypedEntityLinks.java │ │ ├── core │ │ │ ├── AbstractEntityLinks.java │ │ │ ├── AnnotationAttribute.java │ │ │ ├── AnnotationLinkRelationProvider.java │ │ │ ├── AnnotationMappingDiscoverer.java │ │ │ ├── CachingMappingDiscoverer.java │ │ │ ├── ControllerEntityLinks.java │ │ │ ├── ControllerEntityLinksFactoryBean.java │ │ │ ├── DefaultLinkRelationProvider.java │ │ │ ├── DefaultMethodInvocation.java │ │ │ ├── DelegatingEntityLinks.java │ │ │ ├── DelegatingLinkRelationProvider.java │ │ │ ├── DummyInvocationUtils.java │ │ │ ├── EmbeddedWrapper.java │ │ │ ├── EmbeddedWrappers.java │ │ │ ├── EncodingUtils.java │ │ │ ├── EvoInflectorLinkRelationProvider.java │ │ │ ├── HeaderLinksResponseEntity.java │ │ │ ├── LastInvocationAware.java │ │ │ ├── LinkBuilderSupport.java │ │ │ ├── MappingDiscoverer.java │ │ │ ├── MethodInvocation.java │ │ │ ├── MethodParameters.java │ │ │ ├── PropertyResolvingMappingDiscoverer.java │ │ │ ├── RawMappingDiscoverer.java │ │ │ ├── Relation.java │ │ │ ├── SpringAffordanceBuilder.java │ │ │ ├── TemplateVariableAwareLinkBuilderSupport.java │ │ │ ├── TypeReferences.java │ │ │ ├── UriMapping.java │ │ │ ├── UriTemplateFactory.java │ │ │ ├── WebHandler.java │ │ │ └── package-info.java │ │ ├── mvc │ │ │ ├── BasicLinkBuilder.java │ │ │ ├── ControllerLinkRelationProvider.java │ │ │ ├── JacksonSerializers.java │ │ │ ├── MvcLink.java │ │ │ ├── RepresentationModelAssemblerSupport.java │ │ │ ├── RepresentationModelProcessorHandlerMethodReturnValueHandler.java │ │ │ ├── RepresentationModelProcessorInvoker.java │ │ │ ├── TypeConstrainedMappingJackson2HttpMessageConverter.java │ │ │ ├── UriComponentsBuilderFactory.java │ │ │ ├── UriComponentsContributor.java │ │ │ ├── WebMvcLinkBuilder.java │ │ │ ├── WebMvcLinkBuilderFactory.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ └── reactive │ │ │ ├── ReactiveRepresentationModelAssembler.java │ │ │ ├── SimpleReactiveRepresentationModelAssembler.java │ │ │ ├── WebFluxLinkBuilder.java │ │ │ └── package-info.java │ │ └── support │ │ ├── ClassUtils.java │ │ ├── WebStack.java │ │ └── package-info.java ├── javadoc │ ├── doc-files │ │ └── th-background.png │ └── spring-javadoc.css ├── kotlin │ └── org │ │ └── springframework │ │ └── hateoas │ │ └── server │ │ ├── mvc │ │ ├── WebMvcAffordanceBuilderDsl.kt │ │ └── WebMvcLinkBuilderDsl.kt │ │ └── reactive │ │ ├── ReactiveRepresentationModelAssemblerBuildDsl.kt │ │ └── SimpleReactiveRepresentationModelAssemblerBuildDsl.kt └── resources │ └── META-INF │ ├── spring.factories │ └── spring │ └── aot.factories └── test ├── java └── org │ └── springframework │ └── hateoas │ ├── AbstractJackson2MarshallingIntegrationTest.java │ ├── ArchitectureTest.java │ ├── CollectionModelUnitTest.java │ ├── EntityModelIntegrationTest.java │ ├── EntityModelUnitTest.java │ ├── IanaLinkRelationUnitTest.java │ ├── Jackson2LinkIntegrationTest.java │ ├── Jackson2PagedResourcesIntegrationTest.java │ ├── Jackson2ResourceIntegrationTest.java │ ├── Jackson2ResourceSupportIntegrationTest.java │ ├── LinkIntegrationTest.java │ ├── LinkParserUnitTests.java │ ├── LinkRelationUnitTest.java │ ├── LinkUnitTest.java │ ├── LinksUnitTest.java │ ├── MappingTestUtils.java │ ├── PagedModelUnitTest.java │ ├── RepresentationModelIntegrationTest.java │ ├── RepresentationModelUnitTest.java │ ├── SimpleRepresentationModelAssemblerTest.java │ ├── SlicedModelUnitTest.java │ ├── StringLinkRelationUnitTest.java │ ├── TemplateVariablesUnitTest.java │ ├── TestUtils.java │ ├── UriTemplateUnitTest.java │ ├── aot │ ├── AotUtilsUnitTests.java │ ├── HateoasTypesRuntimeHintsUnitTests.java │ └── HypermediaTypesRuntimeHintsUnitTests.java │ ├── client │ ├── Actor.java │ ├── HopUnitTest.java │ ├── Item.java │ ├── LinkDiscovererUnitTest.java │ ├── LinkDiscoverersUnitTest.java │ ├── Movie.java │ ├── Server.java │ └── TraversonTest.java │ ├── config │ ├── CustomHypermediaWebFluxTest.java │ ├── CustomHypermediaWebMvcTest.java │ ├── EnableHypermediaSupportIntegrationTest.java │ ├── HateoasConfigurationIntegrationTest.java │ ├── HypermediaConfigurationImportSelectorUnitTest.java │ ├── HypermediaRestTemplateBeanPostProcessorTest.java │ ├── HypermediaRestTemplateConfigurerTest.java │ ├── HypermediaWebClientBeanPostProcessorTest.java │ ├── HypermediaWebClientConfigurerTest.java │ ├── HypermediaWebFluxConfigurerTest.java │ ├── HypermediaWebMvcConfigurerTest.java │ ├── HypermediaWebTestClientConfigurerTest.java │ ├── RestTemplateHateoasConfigurationIntegrationTest.java │ ├── WebConvertersUnitTests.java │ ├── WebStackImportSelectorUnitTest.java │ └── XmlConfigurationIntegrationTest.java │ ├── mediatype │ ├── AffordancesUnitTests.java │ ├── MediaTypeConfigurationFactoryUnitTests.java │ ├── MediaTypeTestUtils.java │ ├── PropertyUtilsTest.java │ ├── alps │ │ ├── AlpsLinkDiscoverUnitTest.java │ │ ├── AlpsWebFluxIntegrationTest.java │ │ ├── AlpsWebMvcIntegrationTest.java │ │ └── JacksonSerializationTest.java │ ├── collectionjson │ │ ├── CollectionJsonLinkDiscovererUnitTest.java │ │ ├── CollectionJsonSpecTest.java │ │ ├── CollectionJsonWebFluxIntegrationTest.java │ │ ├── CollectionJsonWebMvcIntegrationTest.java │ │ ├── Jackson2CollectionJsonIntegrationTest.java │ │ └── JacksonSerializationTest.java │ ├── hal │ │ ├── CustomizedHalLinkDiscovererUnitTest.java │ │ ├── DefaultCurieProviderUnitTest.java │ │ ├── HalConfigurationUnitTest.java │ │ ├── HalEmbeddedBuilderUnitTest.java │ │ ├── HalLinkDiscovererUnitTest.java │ │ ├── HalLinkRelationUnitTest.java │ │ ├── HalMediaTypeConfigurationIntegrationTest.java │ │ ├── HalModelBuilderUnitTest.java │ │ ├── HalObjectMapperCustomizerTest.java │ │ ├── HalTestUtils.java │ │ ├── Jackson2HalIntegrationTest.java │ │ ├── RenderHypermediaForDefaultAcceptHeadersTest.java │ │ ├── SimpleAnnotatedPojo.java │ │ ├── SimplePojo.java │ │ └── forms │ │ │ ├── HalFormsLinkDiscovererUnitTest.java │ │ │ ├── HalFormsMediaTypeConfigurationIntegrationTest.java │ │ │ ├── HalFormsObjectMapperCustomizerTest.java │ │ │ ├── HalFormsTemplateBuilderUnitTest.java │ │ │ ├── HalFormsWebFluxIntegrationTest.java │ │ │ ├── HalFormsWebMvcIntegrationTest.java │ │ │ └── Jackson2HalFormsIntegrationTest.java │ ├── html │ │ └── HtmlInputTypeUnitTests.java │ ├── problem │ │ ├── HttpProblemDetailsIntegrationTest.java │ │ └── JacksonSerializationTest.java │ └── uber │ │ ├── Jackson2UberIntegrationTest.java │ │ ├── UberLinkDiscovererUnitTest.java │ │ ├── UberWebFluxIntegrationTest.java │ │ └── UberWebMvcIntegrationTest.java │ ├── server │ ├── core │ │ ├── AnnotationLinkRelationProviderUnitTest.java │ │ ├── AnnotationMappingDiscovererUnitTest.java │ │ ├── ControllerEntityLinksFactoryBeanUnitTest.java │ │ ├── ControllerEntityLinksUnitTest.java │ │ ├── DelegatingEntityLinksUnitTest.java │ │ ├── DelegatingRelProviderUnitTest.java │ │ ├── EmbeddedWrappersUnitTest.java │ │ ├── EvoInflectorRelProviderUnitTest.java │ │ ├── JsonPathLinkDiscovererUnitTest.java │ │ ├── LinkBuilderSupportUnitTest.java │ │ ├── MethodParametersUnitTest.java │ │ ├── PropertyResolvingMappingDiscovererUnitTest.java │ │ └── TypeReferencesIntegrationTest.java │ ├── mvc │ │ ├── DummyInvocationUtilsUnitTest.java │ │ ├── HeaderLinksResponseEntityUnitTest.java │ │ ├── HttpEntityMatcher.java │ │ ├── MultiMediaTypeWebMvcIntegrationTest.java │ │ ├── MvcLinkUnitTests.java │ │ ├── RepresentationModelProcessorIntegrationTest.java │ │ ├── RepresentationModelProcessorInvokerUnitTests.java │ │ ├── ResourceProcessorHandlerMethodReturnValueHandlerUnitTest.java │ │ ├── TypeConstrainedMappingJackson2HttpMessageConverterUnitTest.java │ │ ├── WebMvcLinkBuilderFactoryUnitTest.java │ │ ├── WebMvcLinkBuilderOutsideSpringMvcUnitTest.java │ │ └── WebMvcLinkBuilderUnitTest.java │ └── reactive │ │ ├── HypermediaWebFilterTest.java │ │ ├── ReactiveResourceAssemblerUnitTest.java │ │ ├── SimpleReactiveResourceAssemblerTest.java │ │ └── WebFluxLinkBuilderTest.java │ └── support │ ├── ChangelogCreator.java │ ├── ContextTester.java │ ├── CustomHypermediaType.java │ ├── Employee.java │ ├── EmployeeResource.java │ ├── HidingClassLoader.java │ ├── JsonPathUtils.java │ ├── MappingUtils.java │ ├── WebFluxEmployeeController.java │ └── WebMvcEmployeeController.java ├── kotlin └── org │ └── springframework │ └── hateoas │ └── server │ ├── mvc │ ├── WebMvcAffordanceBuilderDslUnitTest.kt │ └── WebMvcLinkBuilderDslUnitTest.kt │ └── reactive │ ├── ReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt │ └── SimpleReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt └── resources ├── logback.xml ├── org └── springframework │ └── hateoas │ ├── config │ ├── application-context.xml │ ├── rest-messages.properties │ ├── webflux-frodo.json │ └── webmvc-frodo.json │ └── mediatype │ ├── alps │ ├── link-discoverer.json │ └── reference.json │ ├── collectionjson │ ├── paged-resources.json │ ├── reference.json │ ├── resource-support-2.json │ ├── resource-support-3.json │ ├── resource-support.json │ ├── resource.json │ ├── resources-simple-pojos.json │ ├── resources-with-resource-objects.json │ ├── resources.json │ ├── single-reactive-employee.json │ ├── spec-part1.json │ ├── spec-part2.json │ ├── spec-part3.json │ ├── spec-part4.json │ ├── spec-part5.json │ ├── spec-part6.json │ ├── spec-part7-adjusted.json │ └── spec-part7.json │ ├── hal │ ├── forms │ │ ├── annotated-embedded-resources-reference.json │ │ ├── annotated-paged-resources.json │ │ ├── annotated-resource-resources.json │ │ ├── curied-document.json │ │ ├── employee-resource-support.json │ │ ├── empty-document.json │ │ ├── empty-embedded-pojos.json │ │ ├── hal-forms-custom.json │ │ ├── hal-forms-link-discoverer.json │ │ ├── hal-forms-link.json │ │ ├── link-template.json │ │ ├── link-with-title.json │ │ ├── list-link-reference.json │ │ ├── multiple-curies-document.json │ │ ├── multiple-resource-resources.json │ │ ├── new-employee.json │ │ ├── reference.json │ │ ├── simple-embedded-resource-reference.json │ │ ├── simple-resource-unwrapped.json │ │ ├── single-embedded-resource-reference.json │ │ ├── single-link-reference.json │ │ └── single-non-curie-document.json │ ├── hal-custom.json │ ├── hal-embedded-author-illustrator.json │ ├── hal-embedded-collection.json │ ├── hal-empty.json │ ├── hal-explicit-and-implicit-relations.json │ ├── hal-link-discoverer.json │ ├── hal-link.json │ ├── hal-multiple-types.json │ ├── hal-one-thing.json │ ├── hal-single-item.json │ ├── hal-two-things.json │ └── zoom-hypermedia.json │ ├── problem │ ├── detail-only.json │ ├── extension.json │ ├── http-status-problem.json │ ├── instance-only.json │ ├── reference-1.json │ ├── reference-2.json │ ├── status-only.json │ ├── title-only.json │ └── type-only.json │ ├── uber │ ├── create-employee.json │ ├── link-discovery.json │ ├── paged-resources-empty-page.json │ ├── paged-resources.json │ ├── reference-links-only.json │ ├── resource-support-2.json │ ├── resource-support-pojo-empty.json │ ├── resource-support-pojo.json │ ├── resource-support.json │ ├── resource-with-empty-pojo.json │ ├── resource-with-simple-pojo.json │ ├── resource-with-templated-link.json │ ├── resource.json │ ├── resource2.json │ ├── resource3.json │ ├── resource4.json │ ├── resources-with-empty-resource-objects.json │ ├── resources-with-resource-objects-and-empty-value.json │ ├── resources-with-resource-objects.json │ └── resources.json │ └── vnderror │ ├── vnderror-multiple-items.json │ ├── vnderror-nested.json │ ├── vnderror-single-item.json │ └── vnderror-string-logref.json ├── pagedresources.xml ├── springagram-item-without-image.json ├── springagram-item.json ├── springagram-items.json └── springagram-root.json /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: CI Build 2 | 3 | on: 4 | push: 5 | branches: [ main, 3.0.x, 2.3.x, 2.2.x, 2.1.x, 2.0.x, 1.5.x ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | name: Build project 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | 16 | - name: Check out sources 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v4 21 | with: 22 | distribution: 'temurin' 23 | java-version: 17 24 | cache: 'maven' 25 | 26 | - name: Build with Maven 27 | run: ./mvnw -B 28 | 29 | - name: Deploy to Artifactory 30 | env: 31 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 32 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 33 | run: ./mvnw -B clean deploy -Pci,artifactory 34 | -------------------------------------------------------------------------------- /.github/workflows/compatibility.yaml: -------------------------------------------------------------------------------- 1 | name: Compatibility builds 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '5 6 * * *' 7 | 8 | jobs: 9 | compatibility: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | branch: ['main', '2.3.x', '2.2.x', '2.1.x'] 16 | spring: ['', 'spring-next', 'spring-61-next'] 17 | kotlin: ['', 'kotlin-next', 'kotlin-2-next'] 18 | jackson: ['', 'jackson-next'] 19 | 20 | name: ${{ matrix.branch }} - ${{ matrix.spring }} ${{ matrix.kotlin }} ${{ matrix.jackson }} 21 | 22 | steps: 23 | 24 | - name: Check out sources 25 | uses: actions/checkout@v4 26 | with: 27 | ref: ${{ matrix.branch }} 28 | 29 | - name: Set up JDK 17 30 | uses: actions/setup-java@v4 31 | with: 32 | distribution: 'temurin' 33 | java-version: 17 34 | cache: 'maven' 35 | 36 | - name: List dependencies 37 | run: ./mvnw -D depedency:list -Dsort 38 | - name: Build 39 | run: ./mvnw -B verify -P${{ matrix.spring }},${{ matrix.kotlin }},${{ matrix.jackson }} --file pom.xml 40 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Documentation 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 0 * * *' 7 | 8 | 9 | jobs: 10 | build: 11 | name: Publish documentation 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | 16 | - name: Check out sources 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v4 21 | with: 22 | distribution: 'temurin' 23 | java-version: 17 24 | cache: 'maven' 25 | 26 | - name: Setup Graphviz 27 | uses: ts-graphviz/setup-graphviz@v2 28 | 29 | - name: Deploy documentation 30 | env: 31 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 32 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 33 | run: ./mvnw -B clean deploy -Pdocumentation 34 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release to Maven Central 2 | 3 | on: 4 | push: 5 | branches: [ "release/release", "release/milestone" ] 6 | 7 | jobs: 8 | build: 9 | name: Release project 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | 14 | - name: Check out sources 15 | uses: actions/checkout@v4 16 | 17 | - name: Set up JDK 17 18 | uses: actions/setup-java@v4 19 | with: 20 | distribution: 'temurin' 21 | java-version: 17 22 | cache: 'maven' 23 | 24 | - name: Install GPG key 25 | run: | 26 | echo "${{ secrets.GPG_PRIVATE_KEY }}" > gpg.asc 27 | echo "${{ secrets.GPG_PASSPHRASE }}" | gpg --batch --yes --passphrase-fd 0 --import gpg.asc 28 | 29 | - name: Release to Sonatype OSSRH 30 | env: 31 | SONATYPE_USER: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }} 32 | SONATYPE_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }} 33 | MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} 34 | run: | 35 | ./mvnw -B clean install -DskipTests 36 | ./mvnw -B clean deploy -Pci,sonatype -s settings.xml 37 | 38 | - name: Setup Graphviz 39 | uses: ts-graphviz/setup-graphviz@v2 40 | 41 | - name: Deploy documentation 42 | env: 43 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 44 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 45 | run: ./mvnw -B clean deploy -Pdocumentation 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .settings/ 3 | .project 4 | .classpath 5 | .factorypath 6 | *.iml 7 | .idea 8 | *.orig 9 | .flattened-pom.xml 10 | .springBeans 11 | credentials.yml 12 | etc/updates.txt 13 | -------------------------------------------------------------------------------- /.mvn/jvm.config: -------------------------------------------------------------------------------- 1 | --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED 2 | --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED 3 | --add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED 4 | --add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED 5 | --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED 6 | --add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED 7 | --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED 8 | --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED 9 | --add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED 10 | --add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED 11 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /application.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | repository: spring-projects/spring-hateoas 3 | sections: 4 | - title: ":star: New Features" 5 | labels: ["type: new feature"] 6 | - title: ":bulb: Improvements" 7 | labels: ["type: enhancement"] 8 | - title: ":beetle: Bugs" 9 | labels: ["type: bug"] 10 | - title: ":book: Documentation" 11 | labels: ["in: documentation"] 12 | - title: ":hammer: Dependency Upgrades" 13 | labels: ["type: dependency-upgrade"] 14 | -------------------------------------------------------------------------------- /etc/backport-ticket.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Format $ticketNumber $targetVersion[] 3 | 4 | sourceGh="GH-$1" 5 | branch=$(git branch --show-current) 6 | json=$(gh issue view $1 --json=title,labels) 7 | 8 | title=$(echo $json | jq -r '.title') 9 | labels=$(echo $json | jq -r '.labels[].name' | paste -sd ',' -) 10 | 11 | number=$1 12 | 13 | # The SHAs of all commits associated with the source ticket 14 | shas=$(git log --grep="$sourceGh" --reverse --format="%H") 15 | 16 | # For each of the target versions 17 | for version in ${@:2} 18 | do 19 | # Turn 1.5.6 into 1.5.x 20 | targetBranch="$(echo "$version" | grep -oE '^[0-9]+\.[0-9]+').x" 21 | 22 | # Checkout target branch and cherry-pick commit 23 | echo "Checking out branch $targetBranch" 24 | git checkout $targetBranch 25 | 26 | # Cherry-pick all previously found SHAs 27 | while IFS= read -r sha 28 | do 29 | echo "Cherry-pick commit $sha from $branch" 30 | git cherry-pick $sha 31 | done <<< $shas 32 | 33 | echo "gh issue create --title \"$title\" --body \"Back-port of $sourceGh.\" --label \"$labels\" --assignee \"@me\" --milestone \"$version\"" 34 | number=$(gh issue create --title "$title" --body "Back-port of $sourceGh." --label "$labels" --assignee "@me" --milestone "$version" | awk -F '/' '{print $NF}') 35 | echo "New ticket number: $number" 36 | 37 | # Replace ticket reference with new one 38 | targetGh="GH-$number" 39 | expression="s/$sourceGh/$targetGh/g" 40 | message=$(git log -1 --pretty=format:"%s" | sed $expression) 41 | 42 | # Update commit message to refer to new ticket 43 | echo "Adapt commit message from $sourceGh to $targetGh" 44 | git commit --amend -m "$message" 45 | done 46 | 47 | # Return to original branch 48 | git checkout $branch 49 | -------------------------------------------------------------------------------- /etc/ide/intellij-formatting.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-hateoas/b50c85045cd678b54b4be77ca72bd1ff05b56b37/etc/ide/intellij-formatting.jar -------------------------------------------------------------------------------- /etc/mappings.txt: -------------------------------------------------------------------------------- 1 | assertj=AssertJ 2 | jackson-bom=Jackson 3 | junit=JUnit 4 | kotlin=Kotlin 5 | kotlinx-coroutines=Kotlin Koroutines 6 | logback=Logback 7 | lombok=Lombok 8 | mockk=Mockk 9 | reactor-bom=Reactor 10 | slf4j=Slf4j 11 | spring=Spring Framework 12 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | lombok.anyConstructor.suppressConstructorProperties=true 2 | lombok.nonNull.exceptionType = IllegalArgumentException 3 | lombok.log.fieldName = LOG 4 | lombok.addLombokGeneratedAnnotation = true 5 | lombok.addNullAnnotations = spring 6 | -------------------------------------------------------------------------------- /settings.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | sonatype-new 8 | ${env.SONATYPE_USER} 9 | ${env.SONATYPE_PASSWORD} 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/AffordancesSample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; 19 | 20 | import org.springframework.hateoas.SimpleRepresentationModelAssemblerTest.Employee; 21 | import org.springframework.hateoas.mediatype.Affordances; 22 | import org.springframework.http.HttpMethod; 23 | 24 | /** 25 | * Manual usage of {@link Affordances}. 26 | * 27 | * @author Oliver Drotbohm 28 | */ 29 | public class AffordancesSample { 30 | 31 | void manualAffordance() { 32 | 33 | // tag::affordances[] 34 | var methodInvocation = methodOn(EmployeeController.class).all(); 35 | 36 | var link = Affordances.of(linkTo(methodInvocation).withSelfRel()) // <1> 37 | 38 | .afford(HttpMethod.POST) // <2> 39 | .withInputAndOutput(Employee.class) // 40 | .withName("createEmployee") // 41 | 42 | .andAfford(HttpMethod.GET) // <3> 43 | .withOutput(Employee.class) // 44 | .addParameters(// 45 | QueryParameter.optional("name"), // 46 | QueryParameter.optional("role")) // 47 | .withName("search") // 48 | 49 | .toLink(); 50 | // end::affordances[] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/CollectionJsonApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.hateoas.config.EnableHypermediaSupport; 20 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 21 | 22 | /** 23 | * @author Greg Turnquist 24 | */ 25 | // tag::code[] 26 | @Configuration 27 | @EnableHypermediaSupport(type = HypermediaType.COLLECTION_JSON) 28 | public class CollectionJsonApplication { 29 | 30 | } 31 | // end::code[] 32 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/EmployeeModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import jakarta.validation.constraints.NotNull; 19 | import jakarta.validation.constraints.Pattern; 20 | import lombok.Data; 21 | 22 | /** 23 | * @author Oliver Drotbohm 24 | */ 25 | // tag:hal-forms-model[] 26 | @Data 27 | public class EmployeeModel extends RepresentationModel { 28 | 29 | @NotNull // 30 | private String name; 31 | 32 | @Pattern(regexp = "[A-Z_]") // 33 | private String role; 34 | } 35 | // end:hal-forms-model[] 36 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/ForwardedEnabledConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.hateoas; 18 | 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.web.filter.ForwardedHeaderFilter; 22 | import org.springframework.web.server.adapter.ForwardedHeaderTransformer; 23 | 24 | /** 25 | * @author Greg Turnquist 26 | */ 27 | @Configuration 28 | public class ForwardedEnabledConfig { 29 | 30 | // tag::code-1[] 31 | @Bean 32 | ForwardedHeaderFilter forwardedHeaderFilter() { 33 | return new ForwardedHeaderFilter(); 34 | } 35 | // end::code-1[] 36 | 37 | // tag::code-2[] 38 | @Bean 39 | ForwardedHeaderTransformer forwardedHeaderTransformer() { 40 | return new ForwardedHeaderTransformer(); 41 | } 42 | // end::code-2[] 43 | } 44 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/HalFormsApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.hateoas.config.EnableHypermediaSupport; 20 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 21 | 22 | /** 23 | * @author Greg Turnquist 24 | */ 25 | // tag::code[] 26 | @Configuration 27 | @EnableHypermediaSupport(type = HypermediaType.HAL_FORMS) 28 | public class HalFormsApplication { 29 | 30 | } 31 | // end::code[] 32 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/PaymentProcessingApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | 21 | /** 22 | * @author Greg Turnquist 23 | */ 24 | // tag::code[] 25 | @Configuration 26 | public class PaymentProcessingApp { 27 | 28 | @Bean 29 | PaymentProcessor paymentProcessor() { 30 | return new PaymentProcessor(); 31 | } 32 | } 33 | // end::code[] 34 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/PaymentProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.hateoas.server.RepresentationModelProcessor; 19 | import org.springframework.hateoas.support.Order; 20 | 21 | /** 22 | * @author Greg Turnquist 23 | */ 24 | // tag::code[] 25 | public class PaymentProcessor implements RepresentationModelProcessor> { // <1> 26 | 27 | @Override 28 | public EntityModel process(EntityModel model) { 29 | 30 | model.add( // <2> 31 | Link.of("/payments/{orderId}").withRel(LinkRelation.of("payments")) // 32 | .expand(model.getContent().getOrderId())); 33 | 34 | return model; // <3> 35 | } 36 | } 37 | // end::code[] 38 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/SampleAppConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.hateoas.mediatype.hal.HalConfiguration; 21 | import org.springframework.hateoas.mediatype.hal.HalConfiguration.RenderSingleLinks; 22 | 23 | /** 24 | * @author Greg Turnquist 25 | */ 26 | 27 | @Configuration 28 | public class SampleAppConfiguration { 29 | 30 | // tag::1[] 31 | @Bean 32 | public HalConfiguration globalPolicy() { 33 | return new HalConfiguration() // 34 | .withRenderSingleLinks(RenderSingleLinks.AS_ARRAY); // <1> 35 | } 36 | // end::1[] 37 | 38 | // tag::2[] 39 | @Bean 40 | public HalConfiguration linkRelationBasedPolicy() { 41 | return new HalConfiguration() // 42 | .withRenderSingleLinksFor( // 43 | IanaLinkRelations.ITEM, RenderSingleLinks.AS_ARRAY) // <1> 44 | .withRenderSingleLinksFor( // 45 | LinkRelation.of("prev"), RenderSingleLinks.AS_SINGLE); // <2> 46 | } 47 | // end::2[] 48 | 49 | // tag::3[] 50 | @Bean 51 | public HalConfiguration patternBasedPolicy() { 52 | return new HalConfiguration() // 53 | .withRenderSingleLinksFor( // 54 | "http*", RenderSingleLinks.AS_ARRAY); // <1> 55 | } 56 | // end::3[] 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/UberApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.hateoas.config.EnableHypermediaSupport; 20 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 21 | 22 | /** 23 | * @author Greg Turnquist 24 | */ 25 | // tag::code[] 26 | @Configuration 27 | @EnableHypermediaSupport(type = HypermediaType.UBER) 28 | public class UberApplication { 29 | 30 | } 31 | // end::code[] 32 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/client/HypermediaConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.springframework.hateoas.client; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.hateoas.config.HypermediaRestTemplateConfigurer; 6 | import org.springframework.hateoas.config.HypermediaWebClientConfigurer; 7 | import org.springframework.web.client.RestTemplate; 8 | import org.springframework.web.reactive.function.client.WebClient; 9 | 10 | @Configuration 11 | public class HypermediaConfiguration { 12 | 13 | // tag::rest-template[] 14 | /** 15 | * Use the {@link HypermediaRestTemplateConfigurer} to configure a {@link RestTemplate}. 16 | */ 17 | @Bean 18 | RestTemplate hypermediaRestTemplate(HypermediaRestTemplateConfigurer configurer) { // <1> 19 | return configurer.registerHypermediaTypes(new RestTemplate()); // <2> 20 | } 21 | // end::rest-template[] 22 | 23 | // tag::web-client[] 24 | @Bean 25 | WebClient.Builder hypermediaWebClient(HypermediaWebClientConfigurer configurer) { // <1> 26 | return configurer.registerHypermediaTypes(WebClient.builder()); // <2> 27 | } 28 | // end::web-client[] 29 | } 30 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/mediatype/problem/PaymentResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.problem; 17 | 18 | import java.net.URI; 19 | import java.util.List; 20 | import java.util.UUID; 21 | 22 | /** 23 | * @author Oliver Drotbohm 24 | */ 25 | class PaymentResult { 26 | 27 | UUID getPaymentId() { 28 | return UUID.randomUUID(); 29 | } 30 | 31 | boolean isSuccess() { 32 | return false; 33 | } 34 | 35 | int getBalance() { 36 | return 30; 37 | } 38 | 39 | UUID getSourceAccountId() { 40 | return UUID.randomUUID(); 41 | } 42 | 43 | UUID getTargetAccountId() { 44 | return UUID.randomUUID(); 45 | } 46 | 47 | AccountDetails getDetails() { 48 | return new AccountDetails(); 49 | } 50 | 51 | static class AccountDetails { 52 | int balance; 53 | List accounts; 54 | } 55 | 56 | int getCost() { 57 | return 50; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/mediatype/problem/PaymentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.problem; 17 | 18 | /** 19 | * @author Oliver Drotbohm 20 | */ 21 | public interface PaymentService { 22 | 23 | PaymentResult issuePayment(long orderId, int amount); 24 | } 25 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/support/Customer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import lombok.RequiredArgsConstructor; 19 | import lombok.Value; 20 | 21 | /** 22 | * @author Greg Turnquist 23 | */ 24 | @Value 25 | @RequiredArgsConstructor 26 | public class Customer { 27 | private final long customerId; 28 | } 29 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/support/Order.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import lombok.RequiredArgsConstructor; 19 | import lombok.Value; 20 | 21 | /** 22 | * @author Greg Turnquist 23 | */ 24 | @Value 25 | @RequiredArgsConstructor 26 | public class Order { 27 | private final long orderId; 28 | private final String state; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/support/Payment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import lombok.RequiredArgsConstructor; 19 | import lombok.Value; 20 | 21 | /** 22 | * @author Greg Turnquist 23 | */ 24 | @Value 25 | @RequiredArgsConstructor 26 | public class Payment { 27 | private final Order order; 28 | private final double amount; 29 | } 30 | -------------------------------------------------------------------------------- /src/docs/java/org/springframework/hateoas/support/PaymentController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import org.springframework.web.bind.annotation.RestController; 19 | 20 | /** 21 | * @author Greg Turnquist 22 | */ 23 | @RestController 24 | public class PaymentController { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/docs/resources/assemblies/docs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | docs 4 | 5 | dir 6 | zip 7 | 8 | false 9 | 10 | 11 | 14 | src/main/resources 15 | 16 | changelog.txt 17 | license.txt 18 | notice.txt 19 | 20 | 21 | dos 22 | 23 | 24 | 28 | target/generated-docs 29 | reference 30 | 31 | 32 | 36 | target/site/apidocs 37 | api 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part1.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/" 5 | } 6 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part3.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", // <1> 5 | "links": [ // <2> 6 | { 7 | "rel": "feed", 8 | "href": "https://example.org/friends/rss" 9 | }, 10 | { 11 | "rel": "queries", 12 | "href": "https://example.org/friends/?queries" 13 | }, 14 | { 15 | "rel": "template", 16 | "href": "https://example.org/friends/?template" 17 | } 18 | ], 19 | "items": [ // <3> 20 | { 21 | "href": "https://example.org/friends/jdoe", 22 | "data": [ // <4> 23 | { 24 | "name": "fullname", 25 | "value": "J. Doe", 26 | "prompt": "Full Name" 27 | }, 28 | { 29 | "name": "email", 30 | "value": "jdoe@example.org", 31 | "prompt": "Email" 32 | } 33 | ], 34 | "links": [ // <5> 35 | { 36 | "rel": "blog", 37 | "href": "https://examples.org/blogs/jdoe", 38 | "prompt": "Blog" 39 | }, 40 | { 41 | "rel": "avatar", 42 | "href": "https://examples.org/images/jdoe", 43 | "prompt": "Avatar", 44 | "render": "image" 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part4.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "queries": [ 6 | { 7 | "rel": "search", 8 | "href": "https://example.org/friends/search", 9 | "prompt": "Search", 10 | "data": [ 11 | { 12 | "name": "search", 13 | "value": "" 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part5.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "template": { 6 | "data": [ 7 | { 8 | "name": "full-name", 9 | "value": "", 10 | "prompt": "Full Name" 11 | }, 12 | { 13 | "name": "email", 14 | "value": "", 15 | "prompt": "Email" 16 | }, 17 | { 18 | "name": "blog", 19 | "value": "", 20 | "prompt": "Blog" 21 | }, 22 | { 23 | "name": "avatar", 24 | "value": "", 25 | "prompt": "Avatar" 26 | } 27 | ] 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part6.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "error": { 6 | "title": "Server Error", 7 | "code": "X1C2", 8 | "message": "The server have encountered an error, please wait and try again." 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/collectionjson/spec-part7.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "data": [ 4 | { 5 | "name": "full-name", 6 | "value": "W. Chandry" 7 | }, 8 | { 9 | "name": "email", 10 | "value": "wchandry@example.org" 11 | }, 12 | { 13 | "name": "blog", 14 | "value": "https://example.org/blogs/wchandry" 15 | }, 16 | { 17 | "name": "avatar", 18 | "value": "https://example.org/images/wchandry" 19 | } 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/forms/hal-forms-sample-with-notes.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName" : "Frodo", 3 | "lastName" : "Baggins", 4 | "role" : "ring bearer", 5 | "_links" : { 6 | "self" : { 7 | "href" : "http://localhost:8080/employees/1" 8 | } 9 | }, 10 | "_templates" : { 11 | "default" : { 12 | "method" : "put", 13 | "properties" : [ { 14 | "name" : "name", 15 | "required" : true 16 | }, { 17 | "name" : "role", 18 | "regex" : "[A-Z_]" 19 | } ] 20 | }, 21 | "partiallyUpdateEmployee" : { // <5> 22 | "method" : "patch", // <6> 23 | "properties" : [ { 24 | "name" : "name" 25 | }, { 26 | "name" : "role", 27 | "regex" : "[A-Z_]" 28 | } ] 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/forms/hal-forms-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName" : "Frodo", 3 | "lastName" : "Baggins", 4 | "role" : "ring bearer", 5 | "_links" : { 6 | "self" : { 7 | "href" : "http://localhost:8080/employees/1" 8 | } 9 | }, 10 | "_templates" : { 11 | "default" : { 12 | "method" : "put", 13 | "properties" : [ { 14 | "name" : "firstName", 15 | "required" : true 16 | }, { 17 | "name" : "lastName", 18 | "required" : true 19 | }, { 20 | "name" : "role", 21 | "required" : true 22 | } ] 23 | }, 24 | "partiallyUpdateEmployee" : { 25 | "method" : "patch", 26 | "properties" : [ { 27 | "name" : "firstName", 28 | "required" : false 29 | }, { 30 | "name" : "lastName", 31 | "required" : false 32 | }, { 33 | "name" : "role", 34 | "required" : false 35 | } ] 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/hal-multiple-entry-link-relation.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "item": [ 4 | { "href": "https://myhost/cart/42" }, 5 | { "href": "https://myhost/inventory/12" } 6 | ] 7 | }, 8 | "customer": "Dave Matthews" 9 | } 10 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/hal-single-entry-link-relation-array.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "item": [{ "href": "https://myhost/inventory/12" }] 4 | }, 5 | "customer": "Dave Matthews" 6 | } 7 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/hal-single-entry-link-relation-object.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "item": { "href": "https://myhost/inventory/12" } 4 | }, 5 | "customer": "Dave Matthews" 6 | } 7 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/hal/hal-with-curies.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "self": { 4 | "href": "https://myhost/person/1" 5 | }, 6 | "curies": { 7 | "name": "ex", 8 | "href": "https://example.com/rels/{rel}", 9 | "templated": true 10 | }, 11 | "ex:orders": { 12 | "href": "https://myhost/person/1/orders" 13 | } 14 | }, 15 | "firstname": "Dave", 16 | "lastname": "Matthews" 17 | } 18 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/problem/response.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "https://example.com/probs/out-of-credit", 3 | "title": "You do not have enough credit.", 4 | "detail": "Your current balance is 30, but that costs 50.", 5 | "instance": "/account/12345/msgs/abc", 6 | "balance": 30, 7 | "accounts": ["/account/12345", 8 | "/account/67890"] 9 | } 10 | -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/mediatype/uber/uber-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "/employees/1" 7 | }, { 8 | "name" : "employee", 9 | "data" : [ { 10 | "name" : "role", 11 | "value" : "ring bearer" 12 | }, { 13 | "name" : "name", 14 | "value" : "Frodo" 15 | } ] 16 | } ] 17 | } 18 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/order-plain.json: -------------------------------------------------------------------------------- 1 | { 2 | "orderId" : "42", 3 | "state" : "AWAITING_PAYMENT", 4 | "_links" : { 5 | "self" : { 6 | "href" : "http://localhost/orders/999" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/docs/resources/org/springframework/hateoas/docs/order-with-payment-link.json: -------------------------------------------------------------------------------- 1 | { 2 | "orderId" : "42", 3 | "state" : "AWAITING_PAYMENT", 4 | "_links" : { 5 | "self" : { 6 | "href" : "http://localhost/orders/999" 7 | }, 8 | "payments" : { // <1> 9 | "href" : "/payments/42" // <2> 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | = Spring HATEOAS - Reference Documentation 2 | Oliver Drotbohm; Greg Turnquist; Jay Bryant 3 | :revnumber: {version} 4 | :revdate: {localdate} 5 | :toc: left 6 | :hide-uri-scheme: 7 | 8 | This project provides some APIs to ease creating REST representations that follow the https://en.wikipedia.org/wiki/HATEOAS[HATEOAS] principle when working with Spring and especially Spring MVC. The core problem it tries to address is link creation and representation assembly. 9 | 10 | (C) 2012-2021 The original authors. 11 | 12 | NOTE: Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically. 13 | 14 | [[preface]] 15 | == Preface 16 | include::migrate-to-1.0.adoc[leveloffset=+2] 17 | include::fundamentals.adoc[leveloffset=+1] 18 | include::server.adoc[leveloffset=+1] 19 | include::mediatypes.adoc[leveloffset=+1] 20 | include::configuration.adoc[leveloffset=+1] 21 | include::client.adoc[leveloffset=+1] 22 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/InputType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static java.lang.annotation.ElementType.*; 19 | import static java.lang.annotation.RetentionPolicy.*; 20 | 21 | import java.lang.annotation.Documented; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Annotation to declare a dedicated input type for a property of an representation model. Input types are usually 27 | * derived from the property's type or JSR-303 validation annotations. Use this annotation to override the type. 28 | *

29 | * Values are usually constrained by {@link HtmlInputType} as most media types align with those semantically. That said, 30 | * the annotation doesn't prescribe the usage of those and is open for extensions. 31 | * 32 | * @author Oliver Drotbohm 33 | * @see HtmlInputType 34 | * @since 1.3 35 | * @soundtrack Boney M - Daddy Cool (Take The Heat Off Me) 36 | */ 37 | @Documented 38 | @Retention(RUNTIME) 39 | @Target({ FIELD, METHOD, ANNOTATION_TYPE }) 40 | public @interface InputType { 41 | String value(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/NonComposite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static java.lang.annotation.ElementType.*; 19 | import static java.lang.annotation.RetentionPolicy.*; 20 | 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Annotation to be used in combination with {@link RequestParam} to indicate that collection based values are supposed 26 | * to be rendered as non-composite values, i.e. like {@code param=value1,value2,value3} rather than 27 | * {@code param=value1¶m=value2} when generating links by pointing to controller methods. 28 | * 29 | * @author Oliver Drotbohm 30 | * @since 1.4 31 | */ 32 | @Retention(RUNTIME) 33 | @Target({ PARAMETER, ANNOTATION_TYPE }) 34 | public @interface NonComposite {} 35 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/aot/HateoasTypesRuntimeHints.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.aot; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | import org.springframework.aot.hint.RuntimeHints; 20 | import org.springframework.aot.hint.RuntimeHintsRegistrar; 21 | import org.springframework.hateoas.RepresentationModel; 22 | 23 | /** 24 | * Registers reflection metadata for {@link RepresentationModel} types. 25 | * 26 | * @author Oliver Drotbohm 27 | */ 28 | class HateoasTypesRuntimeHints implements RuntimeHintsRegistrar { 29 | 30 | /* 31 | * (non-Javadoc) 32 | * @see org.springframework.aot.hint.RuntimeHintsRegistrar#registerHints(org.springframework.aot.hint.RuntimeHints, java.lang.ClassLoader) 33 | */ 34 | @Override 35 | public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { 36 | 37 | var packageName = RepresentationModel.class.getPackageName(); 38 | var reflection = hints.reflection(); 39 | 40 | AotUtils.registerTypesForReflection(packageName, reflection); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/aot/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * AOT support. 3 | * 4 | * @author Christoph Strobl 5 | * @author Oliver Drotbohm 6 | */ 7 | @org.jspecify.annotations.NullMarked 8 | package org.springframework.hateoas.aot; 9 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/client/TraversonDefaults.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.client; 17 | 18 | import java.util.Collection; 19 | import java.util.List; 20 | 21 | import org.springframework.http.MediaType; 22 | import org.springframework.http.converter.HttpMessageConverter; 23 | 24 | /** 25 | * SPI that exposes {@link HttpMessageConverter}s and {@link LinkDiscoverer}s to be used by default by 26 | * {@link Traverson}. Not intended for public implementation. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | public interface TraversonDefaults { 31 | 32 | /** 33 | * Returns the {@link HttpMessageConverter} instances to be registered for the given {@link MediaType}s. 34 | * 35 | * @param mediaTypes will never be {@literal null}. 36 | * @return 37 | */ 38 | List> getHttpMessageConverters(Collection mediaTypes); 39 | 40 | /** 41 | * Returns the {@link LinkDiscoverer}s to be registered by default for the given {@link MediaType}s. 42 | * 43 | * @param mediaTypes will never be {@literal null}. 44 | * @return 45 | */ 46 | List getLinkDiscoverers(Collection mediaTypes); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/client/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Client side support. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.client; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/config/HypermediaRestTemplateConfigurer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import org.springframework.web.client.RestTemplate; 19 | 20 | /** 21 | * Assembles hypermedia-based message converters and applies them to an existing {@link RestTemplate}. 22 | * 23 | * @author Greg Turnquist 24 | * @since 1.1 25 | */ 26 | public class HypermediaRestTemplateConfigurer { 27 | 28 | private final WebConverters converters; 29 | 30 | /** 31 | * Creates a new {@link HypermediaRestTemplateConfigurer} using the {@link WebConverters}. 32 | * 33 | * @param converters 34 | */ 35 | HypermediaRestTemplateConfigurer(WebConverters converters) { 36 | this.converters = converters; 37 | } 38 | 39 | /** 40 | * Insert hypermedia-aware message converters in front of any other existing message converters. 41 | * 42 | * @param template 43 | * @return {@link RestTemplate} capable of speaking hypermedia. 44 | */ 45 | public RestTemplate registerHypermediaTypes(RestTemplate template) { 46 | 47 | converters.augmentClient(template.getMessageConverters()); 48 | 49 | return template; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/config/MediaTypeConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.http.MediaType; 21 | 22 | /** 23 | * SPI used to register internal media types through spring.factories. 24 | * 25 | * WARNING: Do NOT implement this interface if you are coding a custom media type. See "Custom media type configuration" in the reference docs. 26 | * 27 | * @author Oliver Drotbohm 28 | * @author Greg Turnquist 29 | * @see HypermediaMappingInformation 30 | */ 31 | public interface MediaTypeConfigurationProvider { 32 | 33 | /** 34 | * Returns the primary Spring configuration class to be bootstrapped for the given media type. 35 | * 36 | * @return 37 | */ 38 | Class getConfiguration(); 39 | 40 | /** 41 | * Returns whether the provider supports any of the given {@link MediaType}s. Used to select the providers to be 42 | * included into a configuration setup in case the media types to be enabled are explicitly defined. 43 | * 44 | * @param mediaTypes will never be {@literal null}. 45 | * @return 46 | */ 47 | boolean supportsAny(Collection mediaTypes); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/config/WebMvcEntityLinksConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import org.springframework.beans.factory.ObjectProvider; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.hateoas.server.core.ControllerEntityLinksFactoryBean; 22 | import org.springframework.hateoas.server.mvc.WebMvcLinkBuilderFactory; 23 | import org.springframework.stereotype.Controller; 24 | 25 | /** 26 | * Spring WebMVC specific bean definitions to support {@link EntityLinks}. 27 | * 28 | * @author Greg Turnquist 29 | * @author Oliver Gierke 30 | */ 31 | @Configuration(proxyBeanMethods = false) 32 | class WebMvcEntityLinksConfiguration extends EntityLinksConfiguration { 33 | 34 | @Bean 35 | ControllerEntityLinksFactoryBean webMvcEntityLinks(ObjectProvider linkBuilderFactory) { 36 | 37 | ControllerEntityLinksFactoryBean factory = new ControllerEntityLinksFactoryBean(); 38 | factory.setAnnotation(Controller.class); 39 | factory.setLinkBuilderFactory(linkBuilderFactory.getIfAvailable(WebMvcLinkBuilderFactory::new)); 40 | 41 | return factory; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/config/WebTestHateoasConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import java.util.List; 19 | 20 | import org.springframework.beans.factory.ObjectProvider; 21 | import org.springframework.context.annotation.Bean; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.context.annotation.Lazy; 24 | 25 | import com.fasterxml.jackson.databind.ObjectMapper; 26 | 27 | /** 28 | * Configuration for Spring TEST-specific things 29 | * 30 | * @author Greg Turnquist 31 | * @author Oliver Drotbohm 32 | * @since 1.1 33 | */ 34 | @Configuration(proxyBeanMethods = false) 35 | class WebTestHateoasConfiguration { 36 | 37 | @Bean 38 | @Lazy 39 | HypermediaWebTestClientConfigurer webTestClientConfigurer(ObjectProvider mapper, 40 | List hypermediaTypes) { 41 | return new HypermediaWebTestClientConfigurer(mapper.getIfAvailable(ObjectMapper::new), hypermediaTypes); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/config/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring container configuration support. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.config; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/AffordanceModelFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | import org.springframework.hateoas.AffordanceModel; 19 | import org.springframework.http.MediaType; 20 | 21 | /** 22 | * SPI for media type implementations to create a specific {@link AffordanceModel} for a {@link ConfiguredAffordance}. 23 | * 24 | * @author Greg Turnquist 25 | * @author Oliver Gierke 26 | */ 27 | public interface AffordanceModelFactory { 28 | 29 | /** 30 | * Declare the {@link MediaType} this factory supports. 31 | * 32 | * @return 33 | */ 34 | MediaType getMediaType(); 35 | 36 | /** 37 | * Return the {@link AffordanceModel} for the given {@link ConfiguredAffordance}. 38 | * 39 | * @param configured will never be {@literal null}. 40 | * @return must not be {@literal null}. 41 | * @since 1.3 42 | */ 43 | AffordanceModel getAffordanceModel(ConfiguredAffordance configured); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/AffordanceOperations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | import org.springframework.hateoas.Link; 19 | 20 | /** 21 | * Operations commons to all builder APIs. 22 | * 23 | * @author Oliver Drotbohm 24 | * @see ConfigurableAffordance 25 | */ 26 | public interface AffordanceOperations { 27 | 28 | /** 29 | * Returns a {@link Link} equipped with the {@link Affordance} currently under construction. 30 | * 31 | * @return will never be {@literal null}. 32 | */ 33 | Link toLink(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/DefaultOnlyMessageResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | import org.springframework.context.MessageSourceResolvable; 20 | 21 | /** 22 | * {@link MessageResolver} to always resort to the {@link MessageSourceResolvable}'s default message. 23 | * 24 | * @author Oliver Drotbohm 25 | */ 26 | enum DefaultOnlyMessageResolver implements MessageResolver { 27 | 28 | INSTANCE; 29 | 30 | /* 31 | * (non-Javadoc) 32 | * @see org.springframework.hateoas.mediatype.MessageResolver#resolve(org.springframework.context.MessageSourceResolvable) 33 | */ 34 | @Nullable 35 | @Override 36 | public String resolve(MessageSourceResolvable resolvable) { 37 | return resolvable.getDefaultMessage(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/InputTypeFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | 20 | /** 21 | * SPI interface for components that can derive an input type from a {@link ResolvableType}. Primary usage to enable to 22 | * default the resolution to use HTML based {@link org.springframework.hateoas.mediatype.html.HtmlInputType} without 23 | * creating a package cycle. If you want to replace that implementation with a different one, register it in 24 | * {@code META-INF/spring.factories}. 25 | * 26 | * @author Oliver Drotbohm 27 | * @since 1.3 28 | */ 29 | public interface InputTypeFactory { 30 | 31 | /** 32 | * Derive an input type from the given {@link ResolvableType}. 33 | * 34 | * @param type type to resolve the input type for, will never be {@literal null}. 35 | * @return the input type for the given type or {@literal null} if no type could be derived. 36 | */ 37 | @Nullable 38 | String getInputType(Class type); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/JacksonHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | import org.springframework.hateoas.CollectionModel; 19 | import org.springframework.hateoas.EntityModel; 20 | 21 | import com.fasterxml.jackson.databind.JavaType; 22 | 23 | /** 24 | * Jackson utility methods. 25 | */ 26 | public final class JacksonHelper { 27 | 28 | /** 29 | * Navigate a chain of parametric types (e.g. Resources<Resource<String>>) until you find the innermost type (String). 30 | * 31 | * @param contentType 32 | * @return 33 | */ 34 | public static JavaType findRootType(JavaType contentType) { 35 | 36 | if (contentType.hasGenericTypes()) { 37 | return findRootType(contentType.containedType(0)); 38 | } else { 39 | return contentType; 40 | } 41 | } 42 | 43 | /** 44 | * Is this a {@literal Resources>}? 45 | * 46 | * @param type 47 | * @return 48 | */ 49 | public static boolean isResourcesOfResource(JavaType type) { 50 | 51 | return 52 | CollectionModel.class.isAssignableFrom(type.getRawClass()) 53 | && 54 | EntityModel.class.isAssignableFrom(type.containedType(0).getRawClass()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/MediaTypeConfigurationCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype; 17 | 18 | /** 19 | * Callback interface to customize media type-specific configuration. Declare instances of the interface as bean methods 20 | * in Spring configuration. 21 | * 22 | * @author Oliver Drotbohm 23 | * @since 2.2 24 | */ 25 | public interface MediaTypeConfigurationCustomizer { 26 | 27 | /** 28 | * Customize the given configuration instance. 29 | * 30 | * @param configuration will never be {@literal null}. 31 | * @return must not be {@literal null}. 32 | */ 33 | T customize(T configuration); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/alps/AlpsLinkDiscoverer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.alps; 17 | 18 | import org.springframework.hateoas.MediaTypes; 19 | import org.springframework.hateoas.client.JsonPathLinkDiscoverer; 20 | 21 | /** 22 | * {@link LinkDiscoverer} implementation to find ALPS-based links. 23 | * 24 | * @author Greg Turnquist 25 | */ 26 | public class AlpsLinkDiscoverer extends JsonPathLinkDiscoverer { 27 | 28 | public AlpsLinkDiscoverer() { 29 | super("$.descriptors[?(@.name == '%s')].href", MediaTypes.ALPS_JSON); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/alps/Format.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.alps; 17 | 18 | import java.util.Locale; 19 | 20 | /** 21 | * Enum for all ALPS doc formats. 22 | * 23 | * @author Oliver Gierke 24 | * @author Greg Turnquist 25 | * @since 0.15 26 | * @see http://alps.io/spec/#prop-format 27 | */ 28 | public enum Format { 29 | 30 | TEXT, HTML, ASCIIDOC, MARKDOWN; 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see java.lang.Enum#toString() 35 | */ 36 | public String toString() { 37 | return name().toLowerCase(Locale.US); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/alps/Type.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.alps; 17 | 18 | import java.util.Locale; 19 | 20 | /** 21 | * An enum for ALPS descriptor types 22 | * 23 | * @author Oliver Gierke 24 | * @author Greg Turnquist 25 | * @since 0.15 26 | * @see http://alps.io/spec/#prop-type 27 | */ 28 | public enum Type { 29 | 30 | SEMANTIC, SAFE, IDEMPOTENT, UNSAFE; 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see java.lang.Enum#toString() 35 | */ 36 | public String toString() { 37 | return name().toLowerCase(Locale.US); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/alps/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Value objects to build ALPS metadata. 3 | * 4 | * @see https://alps.io 5 | */ 6 | @org.jspecify.annotations.NullMarked 7 | package org.springframework.hateoas.mediatype.alps; 8 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/CollectionJsonAffordanceModelFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.collectionjson; 17 | 18 | import org.springframework.hateoas.AffordanceModel; 19 | import org.springframework.hateoas.MediaTypes; 20 | import org.springframework.hateoas.mediatype.AffordanceModelFactory; 21 | import org.springframework.hateoas.mediatype.ConfiguredAffordance; 22 | import org.springframework.http.MediaType; 23 | 24 | /** 25 | * Factory for creating {@link CollectionJsonAffordanceModel}s. 26 | * 27 | * @author Greg Turnquist 28 | * @author Oliver Drotbohm 29 | */ 30 | class CollectionJsonAffordanceModelFactory implements AffordanceModelFactory { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.mediatype.AffordanceModelFactory#getAffordanceModel(org.springframework.hateoas.mediatype.ConfiguredAffordance) 35 | */ 36 | @Override 37 | public AffordanceModel getAffordanceModel(ConfiguredAffordance configured) { 38 | return new CollectionJsonAffordanceModel(configured); 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.mediatype.AffordanceModelFactory#getMediaType() 44 | */ 45 | @Override 46 | public MediaType getMediaType() { 47 | return MediaTypes.COLLECTION_JSON; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/CollectionJsonMediaTypeConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.collectionjson; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.hateoas.MediaTypes; 21 | import org.springframework.hateoas.config.HypermediaMappingInformation; 22 | import org.springframework.hateoas.config.MediaTypeConfigurationProvider; 23 | import org.springframework.http.MediaType; 24 | 25 | /** 26 | * {@link MediaTypeConfigurationProvider} for Collection/JSON. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class CollectionJsonMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() 35 | */ 36 | @Override 37 | public Class getConfiguration() { 38 | return CollectionJsonMediaTypeConfiguration.class; 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) 44 | */ 45 | @Override 46 | public boolean supportsAny(Collection mediaTypes) { 47 | return mediaTypes.contains(MediaTypes.COLLECTION_JSON); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/CollectionRepresentationModelMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.collectionjson; 17 | 18 | import org.springframework.hateoas.CollectionModel; 19 | import org.springframework.hateoas.mediatype.collectionjson.Jackson2CollectionJsonModule.CollectionJsonResourcesDeserializer; 20 | 21 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 22 | 23 | /** 24 | * Jackson 2 mixin to invoke the related serializer/deserizer. 25 | * 26 | * @author Greg Turnquist 27 | */ 28 | @JsonDeserialize(using = CollectionJsonResourcesDeserializer.class) 29 | abstract class CollectionRepresentationModelMixin extends CollectionModel { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/EntityRepresentationModelMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.collectionjson; 17 | 18 | import org.springframework.hateoas.EntityModel; 19 | import org.springframework.hateoas.mediatype.collectionjson.Jackson2CollectionJsonModule.CollectionJsonResourceDeserializer; 20 | 21 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 22 | 23 | /** 24 | * Jackson 2 mixin to invoke the related serializer/deserizer. 25 | * 26 | * @author Greg Turnquist 27 | */ 28 | @JsonDeserialize(using = CollectionJsonResourceDeserializer.class) 29 | abstract class EntityRepresentationModelMixin extends EntityModel { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/PagedResourcesMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.collectionjson; 17 | 18 | import org.springframework.hateoas.PagedModel; 19 | import org.springframework.hateoas.mediatype.collectionjson.Jackson2CollectionJsonModule.CollectionJsonPagedResourcesDeserializer; 20 | 21 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 22 | 23 | /** 24 | * Jackson 2 mixin to handle {@link PagedModel}. 25 | * 26 | * @author Greg Turnquist 27 | */ 28 | @JsonDeserialize(using = CollectionJsonPagedResourcesDeserializer.class) 29 | abstract class PagedResourcesMixin extends PagedModel { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/collectionjson/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Value objects to build Collection+JSON representations. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype.collectionjson; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/CollectionModelMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.hateoas.CollectionModel; 21 | 22 | import com.fasterxml.jackson.annotation.JsonInclude; 23 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 24 | import com.fasterxml.jackson.annotation.JsonProperty; 25 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 26 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 27 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 28 | 29 | /** 30 | * Custom mixin to to render collection content as {@literal _embedded}. 31 | * 32 | * @author Alexander Baetz 33 | * @author Oliver Gierke 34 | * @author Greg Turnquist 35 | */ 36 | @JsonPropertyOrder({ "content", "links" }) 37 | public abstract class CollectionModelMixin extends CollectionModel { 38 | 39 | @Override 40 | @JsonProperty("_embedded") 41 | @JsonInclude(Include.NON_EMPTY) 42 | @JsonSerialize(using = Jackson2HalModule.HalResourcesSerializer.class) 43 | @JsonDeserialize(using = Jackson2HalModule.HalResourcesDeserializer.class) 44 | public abstract Collection getContent(); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/HalMediaTypeConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.hateoas.MediaTypes; 21 | import org.springframework.hateoas.config.HypermediaMappingInformation; 22 | import org.springframework.hateoas.config.MediaTypeConfigurationProvider; 23 | import org.springframework.http.MediaType; 24 | 25 | /** 26 | * {@link MediaTypeConfigurationProvider} for HAL. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class HalMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.config.HyperMediaTypeProvider#getConfiguration() 35 | */ 36 | @Override 37 | public Class getConfiguration() { 38 | return HalMediaTypeConfiguration.class; 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.config.HyperMediaTypeProvider#supportsAny(java.util.Collection) 44 | */ 45 | @Override 46 | public boolean supportsAny(Collection mediaTypes) { 47 | 48 | return mediaTypes.contains(MediaTypes.HAL_JSON) 49 | || mediaTypes.contains(MediaTypes.VND_HAL_JSON); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/RepresentationModelMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal; 17 | 18 | import org.springframework.hateoas.Links; 19 | import org.springframework.hateoas.RepresentationModel; 20 | 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 23 | import com.fasterxml.jackson.annotation.JsonProperty; 24 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 25 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 26 | 27 | /** 28 | * Custom mixin to render {@link Link}s in HAL. 29 | * 30 | * @author Alexander Baetz 31 | * @author Oliver Gierke 32 | * @author Greg Turnquist 33 | */ 34 | public abstract class RepresentationModelMixin extends RepresentationModel { 35 | 36 | @Override 37 | @JsonProperty("_links") 38 | @JsonInclude(Include.NON_EMPTY) 39 | @JsonSerialize(using = Jackson2HalModule.HalLinkListSerializer.class) 40 | @JsonDeserialize(using = Jackson2HalModule.HalLinkListDeserializer.class) 41 | public abstract Links getLinks(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsAffordanceModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal.forms; 17 | 18 | import org.springframework.hateoas.AffordanceModel; 19 | import org.springframework.hateoas.mediatype.ConfiguredAffordance; 20 | 21 | /** 22 | * {@link AffordanceModel} for a HAL-FORMS {@link MediaType}. 23 | * 24 | * @author Greg Turnquist 25 | * @author Oliver Gierke 26 | */ 27 | class HalFormsAffordanceModel extends AffordanceModel { 28 | 29 | public HalFormsAffordanceModel(ConfiguredAffordance configured) { 30 | super(configured.getNameOrDefault(), configured.getTarget(), configured.getMethod(), configured.getInputMetadata(), 31 | configured.getQueryParameters(), configured.getOutputMetadata()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsAffordanceModelFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal.forms; 17 | 18 | import org.springframework.hateoas.AffordanceModel; 19 | import org.springframework.hateoas.MediaTypes; 20 | import org.springframework.hateoas.mediatype.AffordanceModelFactory; 21 | import org.springframework.hateoas.mediatype.ConfiguredAffordance; 22 | import org.springframework.http.MediaType; 23 | 24 | /** 25 | * Factory for creating {@link HalFormsAffordanceModel}s. 26 | * 27 | * @author Greg Turnquist 28 | * @author Oliver Gierke 29 | */ 30 | class HalFormsAffordanceModelFactory implements AffordanceModelFactory { 31 | 32 | private final MediaType mediaType = MediaTypes.HAL_FORMS_JSON; 33 | 34 | /* 35 | * (non-Javadoc) 36 | * @see org.springframework.hateoas.mediatype.AffordanceModelFactory#getAffordanceModel(org.springframework.hateoas.mediatype.ConfiguredAffordance) 37 | */ 38 | @Override 39 | public AffordanceModel getAffordanceModel(ConfiguredAffordance configured) { 40 | return new HalFormsAffordanceModel(configured); 41 | } 42 | 43 | public MediaType getMediaType() { 44 | return this.mediaType; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsLinkDiscoverer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal.forms; 17 | 18 | import org.springframework.hateoas.MediaTypes; 19 | import org.springframework.hateoas.mediatype.hal.HalLinkDiscoverer; 20 | 21 | /** 22 | * HAL-FORMS based {@link JsonPathLinkDiscoverer}. 23 | * 24 | * @author Greg Turnquist 25 | * @author Oliver Gierke 26 | */ 27 | public class HalFormsLinkDiscoverer extends HalLinkDiscoverer { 28 | 29 | public HalFormsLinkDiscoverer() { 30 | super(MediaTypes.HAL_FORMS_JSON); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/forms/HalFormsMediaTypeConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.hal.forms; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.hateoas.MediaTypes; 21 | import org.springframework.hateoas.config.HypermediaMappingInformation; 22 | import org.springframework.hateoas.config.MediaTypeConfigurationProvider; 23 | import org.springframework.http.MediaType; 24 | 25 | /** 26 | * {@link MediaTypeConfigurationProvider} for HAL Forms. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class HalFormsMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() 35 | */ 36 | @Override 37 | public Class getConfiguration() { 38 | return HalFormsMediaTypeConfiguration.class; 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) 44 | */ 45 | @Override 46 | public boolean supportsAny(Collection mediaTypes) { 47 | return mediaTypes.contains(MediaTypes.HAL_FORMS_JSON); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/forms/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * HAL-FORMS extension media type. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype.hal.forms; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/hal/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * HAL-specific extensions, SPIs and Jackson customizations. 3 | * 4 | * @see http://stateless.co/hal_specification.html 5 | */ 6 | @org.jspecify.annotations.NullMarked 7 | package org.springframework.hateoas.mediatype.hal; 8 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/html/HtmlInputTypeFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.html; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | import org.springframework.hateoas.mediatype.InputTypeFactory; 20 | 21 | /** 22 | * An {@link InputTypeFactory} based on {@link HtmlInputType}. 23 | * 24 | * @author Oliver Drotbohm 25 | * @since 1.3 26 | */ 27 | class HtmlInputTypeFactory implements InputTypeFactory { 28 | 29 | /* 30 | * 31 | * (non-Javadoc) 32 | * @see org.springframework.hateoas.mediatype.InputTypeFactory#getInputType(java.lang.Class) 33 | */ 34 | @Nullable 35 | @Override 36 | public String getInputType(Class type) { 37 | 38 | HtmlInputType inputType = HtmlInputType.from(type); 39 | 40 | return inputType == null ? null : inputType.value(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/html/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support for HTML media type. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype.html; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * General media type support. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/problem/HttpProblemDetailsConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | package org.springframework.hateoas.mediatype.problem; 2 | 3 | import java.util.Collection; 4 | 5 | import org.springframework.hateoas.MediaTypes; 6 | import org.springframework.hateoas.config.HypermediaMappingInformation; 7 | import org.springframework.hateoas.config.MediaTypeConfigurationProvider; 8 | import org.springframework.http.MediaType; 9 | 10 | /** 11 | * {@link MediaTypeConfigurationProvider} for HAL. 12 | * 13 | * @author Oliver Drotbohm 14 | */ 15 | class HttpProblemDetailsConfigurationProvider implements MediaTypeConfigurationProvider { 16 | 17 | /* 18 | * (non-Javadoc) 19 | * @see org.springframework.hateoas.config.HyperMediaTypeProvider#getConfiguration() 20 | */ 21 | @Override 22 | public Class getConfiguration() { 23 | return HttpProblemDetailsMappingInformation.class; 24 | } 25 | 26 | /* 27 | * (non-Javadoc) 28 | * @see org.springframework.hateoas.config.HyperMediaTypeProvider#supportsAny(java.util.Collection) 29 | */ 30 | @Override 31 | public boolean supportsAny(Collection mediaTypes) { 32 | return mediaTypes.contains(MediaTypes.HTTP_PROBLEM_DETAILS_JSON); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/problem/HttpProblemDetailsMappingInformation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.problem; 17 | 18 | import java.util.Collections; 19 | import java.util.List; 20 | 21 | import org.springframework.hateoas.MediaTypes; 22 | import org.springframework.hateoas.config.HypermediaMappingInformation; 23 | import org.springframework.http.MediaType; 24 | 25 | /** 26 | * {@link HypermediaMappingInformation} implementation to setup support for {@link Problem}. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class HttpProblemDetailsMappingInformation implements HypermediaMappingInformation { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.config.HypermediaMappingInformation#getRootType() 35 | */ 36 | @Override 37 | public Class getRootType() { 38 | return Problem.class; 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.config.HypermediaMappingInformation#getMediaTypes() 44 | */ 45 | @Override 46 | public List getMediaTypes() { 47 | return Collections.singletonList(MediaTypes.HTTP_PROBLEM_DETAILS_JSON); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/problem/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Value objects to build Problem representations. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype.problem; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/uber/UberAffordanceModelFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.uber; 17 | 18 | import org.springframework.hateoas.AffordanceModel; 19 | import org.springframework.hateoas.MediaTypes; 20 | import org.springframework.hateoas.mediatype.AffordanceModelFactory; 21 | import org.springframework.hateoas.mediatype.ConfiguredAffordance; 22 | import org.springframework.http.MediaType; 23 | 24 | /** 25 | * {@link AffordanceModelFactory} for {@literal UBER+JSON}. 26 | * 27 | * @author Greg Turnquist 28 | * @author Oliver Drotbohm 29 | */ 30 | class UberAffordanceModelFactory implements AffordanceModelFactory { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.mediatype.AffordanceModelFactory#getAffordanceModel(org.springframework.hateoas.mediatype.ConfiguredAffordance) 35 | */ 36 | @Override 37 | public AffordanceModel getAffordanceModel(ConfiguredAffordance configured) { 38 | return new UberAffordanceModel(configured); 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.mediatype.AffordanceModelFactory#getMediaType() 44 | */ 45 | @Override 46 | public MediaType getMediaType() { 47 | return MediaTypes.UBER_JSON; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/uber/UberMediaTypeConfigurationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.mediatype.uber; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.hateoas.MediaTypes; 21 | import org.springframework.hateoas.config.HypermediaMappingInformation; 22 | import org.springframework.hateoas.config.MediaTypeConfigurationProvider; 23 | import org.springframework.http.MediaType; 24 | 25 | /** 26 | * {@link MediaTypeConfigurationProvider} for Uber. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class UberMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider { 31 | 32 | /* 33 | * (non-Javadoc) 34 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#getConfiguration() 35 | */ 36 | @Override 37 | public Class getConfiguration() { 38 | return UberMediaTypeConfiguration.class; 39 | } 40 | 41 | /* 42 | * (non-Javadoc) 43 | * @see org.springframework.hateoas.config.MediaTypeConfigurationProvider#supportsAny(java.util.Collection) 44 | */ 45 | @Override 46 | public boolean supportsAny(Collection mediaTypes) { 47 | return mediaTypes.contains(MediaTypes.UBER_JSON); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/mediatype/uber/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * UBER media type objects. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.mediatype.uber; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Value objects to ease creating {@link org.springframework.hateoas.Link}s and link driven representations for REST 3 | * webservices. 4 | * 5 | * @author Oliver Drotbohm 6 | * @author Jens Schauder 7 | * @author Greg Turnquist 8 | */ 9 | @org.jspecify.annotations.NullMarked 10 | package org.springframework.hateoas; 11 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/ExposesResourceFor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server; 17 | 18 | import java.lang.annotation.Documented; 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Inherited; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Annotation to demarcate controllers that expose URI templates of a structure according to 27 | * {@link ControllerEntityLinks}. 28 | * 29 | * @author Oliver Gierke 30 | */ 31 | @Inherited 32 | @Documented 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target(ElementType.TYPE) 35 | public @interface ExposesResourceFor { 36 | 37 | /** 38 | * The domain type the controller exposes resources for. 39 | * 40 | * @return 41 | */ 42 | Class value(); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/RepresentationModelProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server; 17 | 18 | import org.springframework.hateoas.RepresentationModel; 19 | 20 | /** 21 | * SPI interface to allow components to process the {@link RepresentationModel} instances returned from Spring MVC 22 | * controllers. 23 | * 24 | * @see EntityModel 25 | * @see CollectionModel 26 | * @author Oliver Gierke 27 | */ 28 | public interface RepresentationModelProcessor> { 29 | 30 | /** 31 | * Processes the given representation model, add links, alter the domain data etc. 32 | * 33 | * @param model 34 | * @return the processed model 35 | */ 36 | T process(T model); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/AbstractEntityLinks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import org.springframework.hateoas.server.EntityLinks; 19 | import org.springframework.hateoas.server.LinkBuilder; 20 | 21 | /** 22 | * Implementation base class to delegate the higher level methods of {@link EntityLinks} by delegating to the more fine 23 | * grained ones to reduce the implementation effort for actual implementation classes. 24 | * 25 | * @author Oliver Gierke 26 | */ 27 | public abstract class AbstractEntityLinks implements EntityLinks { 28 | 29 | /* 30 | * (non-Javadoc) 31 | * @see org.springframework.hateoas.EntityLinks#linkForSingleResource(java.lang.Class, java.lang.Object) 32 | */ 33 | @Override 34 | public LinkBuilder linkForItemResource(Class type, Object id) { 35 | return linkFor(type).slash(id); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/EvoInflectorLinkRelationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import org.atteo.evo.inflector.English; 19 | import org.springframework.hateoas.LinkRelation; 20 | 21 | /** 22 | * {@link LinkRelationProvider} implementation using the Evo Inflector implementation of an algorithmic approach to 23 | * English plurals. 24 | * 25 | * @see http://users.monash.edu/~damian/papers/HTML/Plurals.html 26 | * @author Oliver Gierke 27 | */ 28 | public class EvoInflectorLinkRelationProvider extends DefaultLinkRelationProvider { 29 | 30 | /* 31 | * (non-Javadoc) 32 | * @see org.springframework.hateoas.server.core.DefaultLinkRelationProvider#getCollectionResourceRelFor(java.lang.Class) 33 | */ 34 | @Override 35 | public LinkRelation getCollectionResourceRelFor(Class type) { 36 | return LinkRelation.of(English.plural(getItemResourceRelFor(type).value())); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/LastInvocationAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import java.util.Iterator; 19 | 20 | import org.jspecify.annotations.Nullable; 21 | 22 | /** 23 | * @author Oliver Drotbohm 24 | * @author Greg Turnquist 25 | */ 26 | public interface LastInvocationAware { 27 | 28 | Iterator getObjectParameters(); 29 | 30 | @Nullable 31 | MethodInvocation getLastInvocation(); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/MethodInvocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import java.lang.reflect.Method; 19 | 20 | /** 21 | * @author Oliver Drotbohm 22 | * @author Greg Turnquist 23 | */ 24 | public interface MethodInvocation { 25 | 26 | Object[] getArguments(); 27 | 28 | Method getMethod(); 29 | 30 | Class getTargetType(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/RawMappingDiscoverer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import java.lang.reflect.Method; 19 | 20 | import org.jspecify.annotations.Nullable; 21 | 22 | /** 23 | * An extension of {@link MappingDiscoverer} that allows access to the raw {@link String}-based mapping before turning 24 | * it into a {@link UriMapping}. 25 | * 26 | * @author Oliver Drotbohm 27 | * @since 3.0 28 | */ 29 | interface RawMappingDiscoverer extends MappingDiscoverer { 30 | 31 | /** 32 | * Returns the raw URI mapping associated with the given method of the given class. 33 | * 34 | * @param type can be {@literal null}. 35 | * @param method can be {@literal null}. 36 | * @return can be {@literal null}. 37 | */ 38 | @Nullable 39 | String getMapping(@Nullable Class type, @Nullable Method method); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/UriTemplateFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import java.util.Map; 19 | 20 | import org.jspecify.annotations.Nullable; 21 | import org.springframework.util.Assert; 22 | import org.springframework.util.ConcurrentReferenceHashMap; 23 | import org.springframework.web.util.UriTemplate; 24 | 25 | /** 26 | * Builds and caches {@link UriTemplate} instances. 27 | * 28 | * @author Michal Stochmialek 29 | * @author Oliver Drotbohm 30 | */ 31 | public class UriTemplateFactory { 32 | 33 | private static final Map CACHE = new ConcurrentReferenceHashMap<>(); 34 | 35 | /** 36 | * Returns the the {@link UriTemplate} for the given mapping. 37 | * 38 | * @param mapping must not be {@literal null} or empty. 39 | * @return 40 | */ 41 | public static UriTemplate templateFor(@Nullable String mapping) { 42 | 43 | Assert.hasText(mapping, "Mapping must not be null or empty!"); 44 | 45 | return CACHE.computeIfAbsent(mapping, UriTemplate::new); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementations of core API interfaces. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.server.core; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/mvc/UriComponentsContributor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.mvc; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | import org.springframework.core.MethodParameter; 20 | import org.springframework.web.util.UriComponentsBuilder; 21 | 22 | /** 23 | * SPI callback to enhance a {@link UriComponentsBuilder} when referring to a method through a dummy method invocation. 24 | * Will usually be implemented in implementations of {@link HandlerMethodArgumentResolver} as they represent exactly the 25 | * same functionality inverted. 26 | * 27 | * @see MethodLinkBuilderFactory#linkTo(Object) 28 | * @author Oliver Gierke 29 | */ 30 | public interface UriComponentsContributor { 31 | 32 | /** 33 | * Returns whether the {@link UriComponentsBuilder} supports the given {@link MethodParameter}. 34 | * 35 | * @param parameter will never be {@literal null}. 36 | * @return 37 | */ 38 | boolean supportsParameter(MethodParameter parameter); 39 | 40 | /** 41 | * Enhance the given {@link UriComponentsBuilder} with the given value. 42 | * 43 | * @param builder will never be {@literal null}. 44 | * @param parameter can be {@literal null}. 45 | * @param value can be {@literal null}. 46 | */ 47 | void enhance(UriComponentsBuilder builder, @Nullable MethodParameter parameter, @Nullable Object value); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/mvc/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring MVC helper classes to build {@link org.springframework.hateoas.Link}s and assemble 3 | * {@link org.springframework.hateoas.RepresentationModel} types. 4 | */ 5 | @org.jspecify.annotations.NullMarked 6 | package org.springframework.hateoas.server.mvc; 7 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Server-side components for hypermedia handling. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.server; 6 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/server/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring WebFlux components to build {@link org.springframework.hateoas.Link}s and assemble 3 | * {@link org.springframework.hateoas.RepresentationModel} types. 4 | */ 5 | @org.jspecify.annotations.NullMarked 6 | package org.springframework.hateoas.server.reactive; 7 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/support/ClassUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import org.jspecify.annotations.Nullable; 19 | 20 | /** 21 | * @author Oliver Drotbohm 22 | */ 23 | public class ClassUtils { 24 | 25 | @Nullable 26 | @SuppressWarnings("unchecked") 27 | public static Class loadIfPresent(String type) { 28 | 29 | try { 30 | return (Class) org.springframework.util.ClassUtils.forName(type, 31 | org.springframework.hateoas.support.ClassUtils.class.getClassLoader()); 32 | } catch (ClassNotFoundException | LinkageError e) { 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/springframework/hateoas/support/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support utilities for hypermedia handling. 3 | */ 4 | @org.jspecify.annotations.NullMarked 5 | package org.springframework.hateoas.support; 6 | -------------------------------------------------------------------------------- /src/main/javadoc/doc-files/th-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-projects/spring-hateoas/b50c85045cd678b54b4be77ca72bd1ff05b56b37/src/main/javadoc/doc-files/th-background.png -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.hateoas.mediatype.AffordanceModelFactory=\ 2 | org.springframework.hateoas.mediatype.collectionjson.CollectionJsonAffordanceModelFactory,\ 3 | org.springframework.hateoas.mediatype.hal.forms.HalFormsAffordanceModelFactory,\ 4 | org.springframework.hateoas.mediatype.uber.UberAffordanceModelFactory 5 | 6 | org.springframework.hateoas.config.MediaTypeConfigurationProvider=\ 7 | org.springframework.hateoas.mediatype.collectionjson.CollectionJsonMediaTypeConfigurationProvider,\ 8 | org.springframework.hateoas.mediatype.hal.HalMediaTypeConfigurationProvider,\ 9 | org.springframework.hateoas.mediatype.hal.forms.HalFormsMediaTypeConfigurationProvider,\ 10 | org.springframework.hateoas.mediatype.uber.UberMediaTypeConfigurationProvider,\ 11 | org.springframework.hateoas.mediatype.problem.HttpProblemDetailsConfigurationProvider 12 | 13 | org.springframework.hateoas.client.TraversonDefaults=\ 14 | org.springframework.hateoas.mediatype.hal.HalTraversonDefaults 15 | 16 | org.springframework.hateoas.mediatype.InputTypeFactory=\ 17 | org.springframework.hateoas.mediatype.html.HtmlInputTypeFactory 18 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring/aot.factories: -------------------------------------------------------------------------------- 1 | org.springframework.beans.factory.aot.BeanRegistrationAotProcessor=\ 2 | org.springframework.hateoas.aot.ControllerMethodReturnTypeAotProcessor,\ 3 | org.springframework.hateoas.aot.HypermediaTypeAotProcessor,\ 4 | org.springframework.hateoas.aot.RepresentationModelAssemblerAotProcessor 5 | 6 | org.springframework.aot.hint.RuntimeHintsRegistrar=\ 7 | org.springframework.hateoas.aot.HateoasTypesRuntimeHints 8 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/AbstractJackson2MarshallingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import java.io.StringWriter; 19 | import java.io.Writer; 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | 25 | /** 26 | * Base class to test objects against the Jackson 2.0 {@link ObjectMapper}. 27 | * 28 | * @author Oliver Gierke 29 | * @author Jon Brisbin 30 | * @author Greg Turnquist 31 | */ 32 | @Deprecated 33 | public abstract class AbstractJackson2MarshallingIntegrationTest { 34 | 35 | protected ObjectMapper mapper; 36 | 37 | @BeforeEach 38 | void setUp() { 39 | mapper = MappingTestUtils.defaultObjectMapper(); 40 | } 41 | 42 | protected String write(Object object) throws Exception { 43 | Writer writer = new StringWriter(); 44 | mapper.writeValue(writer, object); 45 | return writer.toString(); 46 | } 47 | 48 | protected T read(String source, Class targetType) throws Exception { 49 | return mapper.readValue(source, targetType); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/Jackson2LinkIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | /** 23 | * Integration tests for {@link org.springframework.hateoas.Link} marshaling. 24 | * 25 | * @author Oliver Gierke 26 | * @author Jon Brisbin 27 | */ 28 | class Jackson2LinkIntegrationTest extends AbstractJackson2MarshallingIntegrationTest { 29 | 30 | private static final String REFERENCE = "{\"rel\":\"something\",\"href\":\"location\"}"; 31 | 32 | /** 33 | * @see #27 34 | */ 35 | @Test 36 | void writesLinkCorrectly() throws Exception { 37 | assertThat(write(Link.of("location", "something"))).isEqualTo(REFERENCE); 38 | } 39 | 40 | /** 41 | * @see #27 42 | */ 43 | @Test 44 | void readsLinkCorrectly() throws Exception { 45 | Link result = read(REFERENCE, Link.class); 46 | assertThat(result.getHref()).isEqualTo("location"); 47 | assertThat(result.getRel()).isEqualTo(LinkRelation.of("something")); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/Jackson2ResourceIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.springframework.hateoas; 2 | 3 | import static org.assertj.core.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 8 | 9 | /** 10 | * Integration tests for {@link EntityModel}. 11 | * 12 | * @author Oliver Gierke 13 | * @author Jon Brisbin 14 | */ 15 | class Jackson2ResourceIntegrationTest extends AbstractJackson2MarshallingIntegrationTest { 16 | 17 | static final String REFERENCE = "{\"firstname\":\"Dave\",\"lastname\":\"Matthews\",\"links\":[{\"rel\":\"self\",\"href\":\"localhost\"}]}"; 18 | 19 | /** 20 | * @see #27 21 | * @throws Exception 22 | */ 23 | @Test 24 | void inlinesContent() throws Exception { 25 | 26 | Person person = new Person(); 27 | person.firstname = "Dave"; 28 | person.lastname = "Matthews"; 29 | 30 | EntityModel resource = EntityModel.of(person); 31 | resource.add(Link.of("localhost")); 32 | 33 | assertThat(write(resource)).isEqualTo(REFERENCE); 34 | } 35 | 36 | /** 37 | * @see #27 38 | */ 39 | @Test 40 | void readsResourceSupportCorrectly() throws Exception { 41 | 42 | PersonResource result = read(REFERENCE, PersonResource.class); 43 | 44 | assertThat(result.getLinks()).hasSize(1); 45 | assertThat(result.getLinks()).contains(Link.of("localhost")); 46 | assertThat(result.getContent().firstname).isEqualTo("Dave"); 47 | assertThat(result.getContent().lastname).isEqualTo("Matthews"); 48 | } 49 | 50 | static class PersonResource extends EntityModel { 51 | 52 | public PersonResource() { 53 | 54 | } 55 | } 56 | 57 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) 58 | static class Person { 59 | 60 | String firstname; 61 | String lastname; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/Jackson2ResourceSupportIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | /** 23 | * Integration tests for {@link org.springframework.hateoas.RepresentationModel}. 24 | * 25 | * @author Oliver Gierke 26 | */ 27 | class Jackson2ResourceSupportIntegrationTest extends AbstractJackson2MarshallingIntegrationTest { 28 | 29 | static final String REFERENCE = "{\"links\":[{\"rel\":\"self\",\"href\":\"localhost\"}]}"; 30 | 31 | /** 32 | * @see #27 33 | */ 34 | @Test 35 | void doesNotRenderId() throws Exception { 36 | 37 | RepresentationModel resourceSupport = new RepresentationModel<>(); 38 | resourceSupport.add(Link.of("localhost")); 39 | 40 | assertThat(write(resourceSupport)).isEqualTo(REFERENCE); 41 | } 42 | 43 | /** 44 | * @see #27 45 | */ 46 | @Test 47 | void readResourceSupportCorrectly() throws Exception { 48 | 49 | RepresentationModel result = read(REFERENCE, RepresentationModel.class); 50 | 51 | assertThat(result.getLinks()).hasSize(1); 52 | assertThat(result.getLinks()).contains(Link.of("localhost")); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/LinkIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | /** 23 | * Integration tests for {@link Link} marshaling. 24 | * 25 | * @author Oliver Gierke 26 | */ 27 | class LinkIntegrationTest extends AbstractJackson2MarshallingIntegrationTest { 28 | 29 | private static final String REFERENCE = "{\"rel\":\"something\",\"href\":\"location\"}"; 30 | 31 | /** 32 | * @see #14 33 | */ 34 | @Test 35 | void writesLinkCorrectly() throws Exception { 36 | assertThat(write(Link.of("location", "something"))).isEqualTo(REFERENCE); 37 | } 38 | 39 | /** 40 | * @see #14 41 | */ 42 | @Test 43 | void readsLinkCorrectly() throws Exception { 44 | 45 | Link result = read(REFERENCE, Link.class); 46 | assertThat(result.getHref()).isEqualTo("location"); 47 | assertThat(result.getRel()).isEqualTo(LinkRelation.of("something")); 48 | assertThat(result.getAffordances()).hasSize(0); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/RepresentationModelIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | /** 23 | * Integration tests for {@link RepresentationModel}. 24 | * 25 | * @author Oliver Gierke 26 | */ 27 | class RepresentationModelIntegrationTest extends AbstractJackson2MarshallingIntegrationTest { 28 | 29 | static final String REFERENCE = "{\"links\":[{\"rel\":\"self\",\"href\":\"localhost\"}]}"; 30 | 31 | @Test // #7 32 | void doesNotRenderId() throws Exception { 33 | 34 | RepresentationModel model = new RepresentationModel<>(); 35 | model.add(Link.of("localhost")); 36 | 37 | assertThat(write(model)).isEqualTo(REFERENCE); 38 | } 39 | 40 | @Test // #14 41 | void readResourceSupportCorrectly() throws Exception { 42 | 43 | RepresentationModel model = read(REFERENCE, RepresentationModel.class); 44 | 45 | assertThat(model.getLinks()).hasSize(1); 46 | assertThat(model.getLinks()).contains(Link.of("localhost")); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/StringLinkRelationUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 23 | import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 24 | import com.fasterxml.jackson.databind.ObjectMapper; 25 | 26 | /** 27 | * Unit tests for {@link StringLinkRelation}. 28 | * 29 | * @author Oliver Gierke 30 | */ 31 | class StringLinkRelationUnitTest { 32 | 33 | @Test 34 | void serializesAsPlainString() throws Exception { 35 | 36 | Sample sample = new Sample(); 37 | sample.relation = StringLinkRelation.of("foo"); 38 | 39 | ObjectMapper mapper = new ObjectMapper(); 40 | 41 | assertThat(mapper.writeValueAsString(sample)).isEqualTo("{\"relation\":\"foo\"}"); 42 | } 43 | 44 | @Test 45 | void deserializesUsingFactoryMethod() throws Exception { 46 | 47 | ObjectMapper mapper = new ObjectMapper(); 48 | 49 | Sample result = mapper.readValue("{\"relation\":\"foo\"}", Sample.class); 50 | 51 | assertThat(result.relation).isEqualTo(StringLinkRelation.of("foo")); 52 | } 53 | 54 | @JsonAutoDetect(fieldVisibility = Visibility.ANY) 55 | static class Sample { 56 | StringLinkRelation relation; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/aot/AotUtilsUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.aot; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.aot.hint.TypeReference; 22 | import org.springframework.hateoas.Link; 23 | import org.springframework.hateoas.RepresentationModel; 24 | 25 | /** 26 | * Unit tests for {@link AotUtils}. 27 | * 28 | * @author Oliver Drotbohm 29 | */ 30 | class AotUtilsUnitTests { 31 | 32 | @Test // GH-1981 33 | void findsTypesInPackage() { 34 | 35 | var scanner = AotUtils.getScanner(Link.class.getPackageName()); 36 | 37 | assertThat(scanner.findClasses()) 38 | .extracting(TypeReference::getName) 39 | .contains(Link.class.getName(), // 40 | RepresentationModel.class.getName(), 41 | "org.springframework.hateoas.EntityModel$MapSuppressingUnwrappingSerializer"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/aot/HateoasTypesRuntimeHintsUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.aot; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.aot.hint.RuntimeHints; 22 | import org.springframework.aot.hint.TypeHint; 23 | import org.springframework.aot.hint.TypeReference; 24 | import org.springframework.hateoas.Link; 25 | import org.springframework.hateoas.Links; 26 | 27 | /** 28 | * Unit tests for {@link RepresentationModelRuntimeHints}. 29 | * 30 | * @author Oliver Drotbohm 31 | */ 32 | class HateoasTypesRuntimeHintsUnitTests { 33 | 34 | @Test // GH-1981 35 | void registersHintsForHateoasTypes() { 36 | 37 | var registrar = new HateoasTypesRuntimeHints(); 38 | var hints = new RuntimeHints(); 39 | 40 | registrar.registerHints(hints, getClass().getClassLoader()); 41 | 42 | assertThat(hints.reflection().typeHints()) 43 | .extracting(TypeHint::getType) 44 | .extracting(TypeReference::getSimpleName) 45 | .contains("MapSuppressingUnwrappingSerializer", // 46 | Link.class.getSimpleName(), // 47 | Links.class.getSimpleName()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/aot/HypermediaTypesRuntimeHintsUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.aot; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.aot.hint.RuntimeHints; 22 | import org.springframework.aot.hint.TypeHint; 23 | import org.springframework.aot.hint.TypeReference; 24 | import org.springframework.hateoas.mediatype.hal.LinkMixin; 25 | import org.springframework.hateoas.mediatype.hal.RepresentationModelMixin; 26 | 27 | /** 28 | * Unit tests for {@link HypermediaTypesRuntimeHints}. 29 | * 30 | * @author Oliver Drotbohm 31 | */ 32 | class HypermediaTypesRuntimeHintsUnitTests { 33 | 34 | @Test // GH-2024 35 | void registersMixinsForHal() { 36 | 37 | var registrar = new HypermediaTypesRuntimeHints(RepresentationModelMixin.class.getPackageName()); 38 | var hints = new RuntimeHints(); 39 | 40 | registrar.registerHints(hints, getClass().getClassLoader()); 41 | 42 | assertThat(hints.reflection().typeHints()) 43 | .extracting(TypeHint::getType) 44 | .extracting(TypeReference::getSimpleName) 45 | .contains(RepresentationModelMixin.class.getSimpleName()) 46 | .contains(LinkMixin.class.getSimpleName()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/client/Actor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.client; 17 | 18 | import lombok.Data; 19 | 20 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 21 | import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | 24 | @JsonAutoDetect(fieldVisibility = Visibility.ANY) 25 | @Data 26 | public class Actor { 27 | 28 | String name; 29 | 30 | public Actor(@JsonProperty("name") String name) { 31 | this.name = name; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/client/Item.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.client; 17 | 18 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | 21 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) 22 | class Item { 23 | 24 | String image; 25 | String description; 26 | 27 | Item(@JsonProperty("image") String image, @JsonProperty("description") String description) { 28 | this.image = image; 29 | this.description = description; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/client/Movie.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.client; 17 | 18 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 19 | import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 20 | 21 | @JsonAutoDetect(fieldVisibility = Visibility.ANY) 22 | public class Movie { 23 | 24 | String title; 25 | 26 | public Movie(String title) { 27 | this.title = title; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/config/RestTemplateHateoasConfigurationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import org.junit.jupiter.api.Test; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.context.annotation.Import; 21 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 22 | import org.springframework.hateoas.support.ContextTester; 23 | 24 | /** 25 | * Integration tests for {@link RestTemplateHateoasConfiguration}. 26 | * 27 | * @author Oliver Drotbohm 28 | */ 29 | class RestTemplateHateoasConfigurationIntegrationTest { 30 | 31 | @Test // #1119 32 | void bootstrapsWithManualImports() { 33 | ContextTester.withContext(WithImports.class, context -> {}); 34 | } 35 | 36 | @Test // #1119 37 | void bootstrapsViaAnnotationConfiguration() { 38 | ContextTester.withContext(AnnotationConfig.class, context -> {}); 39 | } 40 | 41 | @Configuration 42 | @Import({ HateoasConfiguration.class, RestTemplateHateoasConfiguration.class }) 43 | static class WithImports {} 44 | 45 | @Configuration 46 | @EnableHypermediaSupport(type = HypermediaType.HAL) 47 | static class AnnotationConfig {} 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/config/WebConvertersUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import java.util.Collections; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | import com.fasterxml.jackson.databind.ObjectMapper; 25 | 26 | /** 27 | * Unit tests for {@link WebConverters}. 28 | * 29 | * @author Oliver Drotbohm 30 | */ 31 | class WebConvertersUnitTests { 32 | 33 | @Test // #1657 34 | void augmentsConvertersWithoutHypermediaInformationsRegistered() { 35 | 36 | WebConverters converters = WebConverters.of(new ObjectMapper(), Collections.emptyList()); 37 | 38 | assertThatNoException() // 39 | .isThrownBy(() -> converters.augmentClient(Collections.emptyList())); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/config/XmlConfigurationIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.config; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.context.ConfigurableApplicationContext; 22 | import org.springframework.context.annotation.Configuration; 23 | import org.springframework.context.support.ClassPathXmlApplicationContext; 24 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 25 | import org.springframework.hateoas.server.LinkRelationProvider; 26 | 27 | /** 28 | * Integration tests for using {@link EnableHypermediaSupport} from within XML documents. 29 | * 30 | * @author Oliver Gierke 31 | */ 32 | class XmlConfigurationIntegrationTest { 33 | 34 | /** 35 | * @see #259 36 | */ 37 | @Test 38 | void enablesHyperMediaSupportFromXml() { 39 | 40 | ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml", getClass()); 41 | 42 | assertThat(context.getBean(LinkRelationProvider.class)).isNotNull(); 43 | 44 | context.close(); 45 | } 46 | 47 | @Configuration 48 | @EnableHypermediaSupport(type = HypermediaType.HAL) 49 | static class HypermediaConfiguration {} 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/mediatype/hal/SimpleAnnotatedPojo.java: -------------------------------------------------------------------------------- 1 | package org.springframework.hateoas.mediatype.hal; 2 | 3 | import org.springframework.hateoas.server.core.Relation; 4 | 5 | @Relation(value = "pojo", collectionRelation = "pojos") 6 | public class SimpleAnnotatedPojo extends SimplePojo { 7 | 8 | public SimpleAnnotatedPojo() { 9 | } 10 | 11 | public SimpleAnnotatedPojo(String text, int number) { 12 | setText(text); 13 | setNumber(number); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/mediatype/hal/SimplePojo.java: -------------------------------------------------------------------------------- 1 | package org.springframework.hateoas.mediatype.hal; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | 8 | import com.fasterxml.jackson.annotation.JsonProperty; 9 | 10 | @Data 11 | @Getter(onMethod = @__(@JsonProperty)) 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class SimplePojo { 15 | 16 | private String text; 17 | private int number; 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/server/core/AnnotationLinkRelationProviderUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.hateoas.IanaLinkRelations; 22 | import org.springframework.hateoas.server.LinkRelationProvider; 23 | 24 | /** 25 | * @author Vedran Pavic 26 | */ 27 | class AnnotationLinkRelationProviderUnitTest { 28 | 29 | @Test 30 | void ianaLinkRelationsCanBeUsedForItemAndCollectionRelations() { 31 | 32 | LinkRelationProvider linkRelationProvider = new AnnotationLinkRelationProvider(); 33 | 34 | assertThat(linkRelationProvider.getItemResourceRelFor(Resource.class)).isEqualTo(IanaLinkRelations.ITEM); 35 | assertThat(linkRelationProvider.getCollectionResourceRelFor(Resource.class)) 36 | .isEqualTo(IanaLinkRelations.COLLECTION); 37 | } 38 | 39 | @Relation(itemRelation = IanaLinkRelations.ITEM_VALUE, collectionRelation = IanaLinkRelations.COLLECTION_VALUE) 40 | static class Resource {} 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/server/core/EvoInflectorRelProviderUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.hateoas.LinkRelation; 22 | import org.springframework.hateoas.server.LinkRelationProvider; 23 | 24 | /** 25 | * Unit tests for {@link EvoInflectorLinkRelationProvider}. 26 | * 27 | * @author Oliver Gierke 28 | */ 29 | class EvoInflectorRelProviderUnitTest { 30 | 31 | LinkRelationProvider provider = new EvoInflectorLinkRelationProvider(); 32 | 33 | @Test 34 | void buildsCollectionRelCorrectly() { 35 | assertRels(City.class, "city", "cities"); 36 | assertRels(Person.class, "person", "persons"); 37 | } 38 | 39 | private void assertRels(Class type, String singleRel, String collectionRel) { 40 | 41 | assertThat(provider.getItemResourceRelFor(type)).isEqualTo(LinkRelation.of(singleRel)); 42 | assertThat(provider.getCollectionResourceRelFor(type)).isEqualTo(LinkRelation.of(collectionRel)); 43 | } 44 | 45 | static class Person { 46 | 47 | } 48 | 49 | static class City { 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/server/core/JsonPathLinkDiscovererUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.core; 17 | 18 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.hateoas.client.JsonPathLinkDiscoverer; 22 | import org.springframework.http.MediaType; 23 | 24 | /** 25 | * Unit tests for {@link JsonPathLinkDiscoverer}. 26 | * 27 | * @author Oliver Gierke 28 | */ 29 | class JsonPathLinkDiscovererUnitTest { 30 | 31 | @Test 32 | void rejectsNullPattern() { 33 | 34 | assertThatIllegalArgumentException().isThrownBy(() -> { 35 | new JsonPathLinkDiscoverer(null, MediaType.ALL); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/server/mvc/MvcLinkUnitTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.mvc; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | import static org.springframework.hateoas.server.mvc.MvcLink.*; 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.hateoas.IanaLinkRelations; 23 | import org.springframework.hateoas.TestUtils; 24 | import org.springframework.http.HttpEntity; 25 | import org.springframework.http.ResponseEntity; 26 | import org.springframework.web.bind.annotation.PathVariable; 27 | import org.springframework.web.bind.annotation.RequestMapping; 28 | 29 | /** 30 | * Unit tests for {@link MvcLink}. 31 | * 32 | * @author Oliver Drotbohm 33 | */ 34 | class MvcLinkUnitTests extends TestUtils { 35 | 36 | @Test 37 | void createsLinkPointingToController() { 38 | 39 | Object invocation = on(MyController.class).get("4711"); 40 | String expected = "http://localhost/4711"; 41 | 42 | assertThat(MvcLink.of(invocation, IanaLinkRelations.SELF).getHref()).isEqualTo(expected); 43 | assertThat(MvcLink.of(() -> invocation, IanaLinkRelations.SELF).getHref()).isEqualTo(expected); 44 | } 45 | 46 | static class MyController { 47 | 48 | @RequestMapping("/{id}") 49 | HttpEntity get(@PathVariable String id) { 50 | return ResponseEntity.ok().build(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/server/mvc/WebMvcLinkBuilderOutsideSpringMvcUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.server.mvc; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.hateoas.Link; 24 | import org.springframework.web.context.request.RequestContextHolder; 25 | 26 | /** 27 | * Test cases for {@link ControllerLinkBuilder} that are NOT inside an existing Spring MVC request 28 | * 29 | * @author Greg Turnquist 30 | * @author Oliver Drotbohm 31 | */ 32 | class WebMvcLinkBuilderOutsideSpringMvcUnitTest { 33 | 34 | /** 35 | * Clear out any existing request attributes left behind by other tests 36 | */ 37 | @BeforeEach 38 | void setUp() { 39 | RequestContextHolder.setRequestAttributes(null); 40 | } 41 | 42 | /** 43 | * @see #408 44 | */ 45 | @Test 46 | void requestingLinkOutsideWebRequest() { 47 | 48 | Link link = linkTo( 49 | methodOn(WebMvcLinkBuilderUnitTest.PersonsAddressesController.class, 15).getAddressesForCountry("DE")) 50 | .withSelfRel(); 51 | 52 | assertThat(link).isEqualTo(Link.of("/people/15/addresses/DE").withSelfRel()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/support/Employee.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import jakarta.validation.constraints.NotNull; 19 | import lombok.AllArgsConstructor; 20 | import lombok.Data; 21 | import lombok.With; 22 | 23 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 24 | 25 | /** 26 | * @author Greg Turnquist 27 | */ 28 | @Data 29 | @With 30 | @AllArgsConstructor 31 | @JsonIgnoreProperties(ignoreUnknown = true) 32 | public class Employee { 33 | 34 | private @NotNull String name; 35 | private String role; 36 | 37 | Employee() { 38 | this(null, null); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/support/EmployeeResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import lombok.AllArgsConstructor; 19 | import lombok.Data; 20 | import lombok.EqualsAndHashCode; 21 | import lombok.Getter; 22 | 23 | import org.springframework.hateoas.RepresentationModel; 24 | 25 | import com.fasterxml.jackson.annotation.JsonProperty; 26 | 27 | /** 28 | * @author Greg Turnquist 29 | */ 30 | @Data 31 | @Getter(onMethod = @__(@JsonProperty)) 32 | @EqualsAndHashCode(callSuper = true) 33 | @AllArgsConstructor 34 | public class EmployeeResource extends RepresentationModel { 35 | 36 | private String name; 37 | 38 | public EmployeeResource(EmployeeResource employeeResource) { 39 | 40 | this.name = employeeResource.getName(); 41 | add(employeeResource.getLinks()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/hateoas/support/MappingUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2024 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.hateoas.support; 17 | 18 | import java.io.IOException; 19 | import java.util.Scanner; 20 | 21 | import org.springframework.core.io.Resource; 22 | import org.springframework.hateoas.MappingTestUtils; 23 | 24 | /** 25 | * @author Greg Turnquist 26 | */ 27 | public final class MappingUtils { 28 | 29 | /** 30 | * Read test files. 31 | * 32 | * @param resource as a {@link Resource} 33 | * @return 34 | * @throws IOException 35 | * @deprecated 1.1, use {@link MappingTestUtils} instead. 36 | */ 37 | @Deprecated 38 | public static String read(Resource resource) throws IOException { 39 | 40 | try (Scanner scanner = new Scanner(resource.getInputStream())) { 41 | 42 | StringBuilder builder = new StringBuilder(); 43 | 44 | while (scanner.hasNextLine()) { 45 | 46 | builder.append(scanner.nextLine()); 47 | 48 | if (scanner.hasNextLine()) { 49 | builder.append(System.lineSeparator()); 50 | } 51 | } 52 | 53 | return builder.toString(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d %5p %40.40c:%4L - %m%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/config/application-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/config/rest-messages.properties: -------------------------------------------------------------------------------- 1 | key=Schlüssel 2 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/config/webflux-frodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Frodo Baggins", 3 | "role" : "ring bearer", 4 | "links" : [ { 5 | "rel" : "self", 6 | "href" : "http://localhost/employees/1" 7 | } ] 8 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/config/webmvc-frodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Frodo Baggins", 3 | "role" : "ring bearer", 4 | "links" : [ { 5 | "rel" : "self", 6 | "href" : "http://localhost/employees/1" 7 | } ] 8 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/alps/link-discoverer.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "doc" : { 4 | "href" : "https://example.org/samples/full/doc.html" 5 | }, 6 | "descriptors" : [ { 7 | "id" : "sfirst descriptor", 8 | "name" : "relation", 9 | "href" : "firstHref" 10 | }, { 11 | "id" : "second description", 12 | "name" : "relation", 13 | "href" : "secondHref" 14 | }, { 15 | "id" : "self descriptor", 16 | "name" : "self", 17 | "href" : "selfHref" 18 | }, { 19 | "id" : "fully qualified descriptor", 20 | "name" : "http://www.foo.com/bar", 21 | "href" : "fullRelHref" 22 | } ] 23 | } 24 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/alps/reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "doc" : { 4 | "href" : "https://example.org/samples/full/doc.html" 5 | }, 6 | "descriptor" : [ { 7 | "id" : "search", 8 | "type" : "SAFE", 9 | "doc" : { 10 | "format" : "TEXT", 11 | "value" : "A search form with two inputs." 12 | }, 13 | "descriptor" : [ { 14 | "href" : "#resultType" 15 | }, { 16 | "id" : "value", 17 | "name" : "search", 18 | "type" : "SEMANTIC" 19 | } ] 20 | }, { 21 | "id" : "resultType", 22 | "type" : "SEMANTIC", 23 | "doc" : { 24 | "value" : "results format" 25 | }, 26 | "ext" : { 27 | "id" : "#ext-range", 28 | "href" : "http://alps.io/ext/range", 29 | "value" : "summary,detail" 30 | } 31 | } ] 32 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/paged-resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "links" : [ { 6 | "rel" : "next", 7 | "href" : "foo" 8 | }, { 9 | "rel" : "prev", 10 | "href" : "bar" 11 | } ], 12 | "items" : [ { 13 | "href" : "localhost", 14 | "data" : [ { 15 | "name" : "number", 16 | "value" : 1 17 | }, { 18 | "name" : "text", 19 | "value" : "test1" 20 | } ] 21 | }, { 22 | "href" : "localhost", 23 | "data" : [ { 24 | "name" : "number", 25 | "value" : 2 26 | }, { 27 | "name" : "text", 28 | "value" : "test2" 29 | } ] 30 | } ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "version" : "1.0", 3 | "href" : "localhost", 4 | "links" : [ { 5 | "rel" : "self", 6 | "href" : "foo" 7 | } ], 8 | "items" : [ { 9 | "href" : "localhost", 10 | "data" : [ { 11 | "value" : "Greetings programs" 12 | } ], 13 | "links" : [ { 14 | "rel" : "self", 15 | "href" : "localhost" 16 | } ] 17 | }, { 18 | "href" : "localhost", 19 | "data" : [ { 20 | "value" : "Yo" 21 | } ], 22 | "links" : [ { 23 | "rel" : "orders", 24 | "href" : "localhost/orders" 25 | } ] 26 | } ] 27 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resource-support-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "links" : [ { 6 | "rel" : "orders", 7 | "href" : "localhost2" 8 | } ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resource-support-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "items" : [ { 6 | "href" : "localhost", 7 | "data" : [ { 8 | "name" : "attribute", 9 | "value" : "test value" 10 | } ] 11 | } ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resource-support.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "items" : [ { 6 | "href" : "localhost", 7 | "data" : [ { 8 | "value" : "first" 9 | } ] 10 | } ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resources-simple-pojos.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "links" : [ { 6 | "rel" : "next", 7 | "href" : "/page/2" 8 | } ], 9 | "items" : [ { 10 | "href" : "localhost", 11 | "data" : [ { 12 | "name" : "number", 13 | "value" : 1 14 | }, { 15 | "name" : "text", 16 | "value" : "text" 17 | } ], 18 | "links" : [ { 19 | "rel" : "orders", 20 | "href" : "orders" 21 | } ] 22 | }, { 23 | "href" : "localhost", 24 | "data" : [ { 25 | "name" : "number", 26 | "value" : 2 27 | }, { 28 | "name" : "text", 29 | "value" : "text2" 30 | } ] 31 | } ] 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resources-with-resource-objects.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "links" : [ { 6 | "rel" : "next", 7 | "href" : "/page/2" 8 | } ], 9 | "items" : [ { 10 | "href" : "localhost", 11 | "data" : [ { 12 | "value" : "first" 13 | } ], 14 | "links" : [ { 15 | "rel" : "orders", 16 | "href" : "orders" 17 | } ] 18 | }, { 19 | "href" : "remotehost", 20 | "data" : [ { 21 | "value" : "second" 22 | } ], 23 | "links" : [ { 24 | "rel" : "orders", 25 | "href" : "order" 26 | } ] 27 | } ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection" : { 3 | "version" : "1.0", 4 | "href" : "localhost", 5 | "items" : [ { 6 | "href" : null, 7 | "data" : [ { 8 | "value" : "first" 9 | } ] 10 | }, { 11 | "href" : null, 12 | "data" : [ { 13 | "value" : "second" 14 | } ] 15 | } ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/single-reactive-employee.json: -------------------------------------------------------------------------------- 1 | {"collection":{"version":"1.0","href":"http://localhost/employees/0","links":[{"rel":"employees","href":"http://localhost/employees"}],"items":[{"href":"http://localhost/employees/0","data":[{"name":"role","value":"ring bearer"},{"name":"name","value":"Frodo Baggins"}],"links":[{"rel":"employees","href":"http://localhost/employees"}]}],"template":{"data":[{"name":"name","value":""},{"name":"role","value":""}]}}} -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part1.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/" 5 | } 6 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part3.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "links": [ 6 | { 7 | "rel": "feed", 8 | "href": "https://example.org/friends/rss" 9 | }, 10 | { 11 | "rel": "queries", 12 | "href": "https://example.org/friends/?queries" 13 | }, 14 | { 15 | "rel": "template", 16 | "href": "https://example.org/friends/?template" 17 | } 18 | ], 19 | "items": [ 20 | { 21 | "href": "https://example.org/friends/jdoe", 22 | "data": [ 23 | { 24 | "name": "fullname", 25 | "value": "J. Doe", 26 | "prompt": "Full Name" 27 | }, 28 | { 29 | "name": "email", 30 | "value": "jdoe@example.org", 31 | "prompt": "Email" 32 | } 33 | ], 34 | "links": [ 35 | { 36 | "rel": "blog", 37 | "href": "https://examples.org/blogs/jdoe", 38 | "prompt": "Blog" 39 | }, 40 | { 41 | "rel": "avatar", 42 | "href": "https://examples.org/images/jdoe", 43 | "prompt": "Avatar", 44 | "render": "image" 45 | } 46 | ] 47 | } 48 | ] 49 | } 50 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part4.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "queries": [ 6 | { 7 | "rel": "search", 8 | "href": "https://example.org/friends/search", 9 | "prompt": "Search", 10 | "data": [ 11 | { 12 | "name": "search", 13 | "value": "" 14 | } 15 | ] 16 | } 17 | ] 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part5.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "template": { 6 | "data": [ 7 | { 8 | "name": "full-name", 9 | "value": "", 10 | "prompt": "Full Name" 11 | }, 12 | { 13 | "name": "email", 14 | "value": "", 15 | "prompt": "Email" 16 | }, 17 | { 18 | "name": "blog", 19 | "value": "", 20 | "prompt": "Blog" 21 | }, 22 | { 23 | "name": "avatar", 24 | "value": "", 25 | "prompt": "Avatar" 26 | } 27 | ] 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part6.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": { 3 | "version": "1.0", 4 | "href": "https://example.org/friends/", 5 | "error": { 6 | "title": "Server Error", 7 | "code": "X1C2", 8 | "message": "The server have encountered an error, please wait and try again." 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part7-adjusted.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "data": [ 4 | { 5 | "name": "name", 6 | "value": "W. Chandry" 7 | }, 8 | { 9 | "name": "role", 10 | "value": "developer" 11 | }, 12 | { 13 | "name": "blog", 14 | "value": "https://example.org/blogs/wchandry" 15 | }, 16 | { 17 | "name": "avatar", 18 | "value": "https://example.org/images/wchandry" 19 | } 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/collectionjson/spec-part7.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": { 3 | "data": [ 4 | { 5 | "name": "full-name", 6 | "value": "W. Chandry" 7 | }, 8 | { 9 | "name": "email", 10 | "value": "wchandry@example.org" 11 | }, 12 | { 13 | "name": "blog", 14 | "value": "https://example.org/blogs/wchandry" 15 | }, 16 | { 17 | "name": "avatar", 18 | "value": "https://example.org/images/wchandry" 19 | } 20 | ] 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/annotated-embedded-resources-reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "pojos" : [ { 4 | "text" : "test1", 5 | "number" : 1, 6 | "_links" : { 7 | "self" : { 8 | "href" : "localhost" 9 | } 10 | } 11 | }, { 12 | "text" : "test2", 13 | "number" : 2, 14 | "_links" : { 15 | "self" : { 16 | "href" : "localhost" 17 | } 18 | } 19 | } ] 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/annotated-paged-resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "pojos" : [ { 4 | "text" : "test1", 5 | "number" : 1, 6 | "_links" : { 7 | "self" : { 8 | "href" : "localhost" 9 | } 10 | } 11 | }, { 12 | "text" : "test2", 13 | "number" : 2, 14 | "_links" : { 15 | "self" : { 16 | "href" : "localhost" 17 | } 18 | } 19 | } ] 20 | }, 21 | "_links" : { 22 | "next" : { 23 | "href" : "foo" 24 | }, 25 | "prev" : { 26 | "href" : "bar" 27 | } 28 | }, 29 | "page" : { 30 | "size" : 2, 31 | "totalElements" : 4, 32 | "totalPages" : 2, 33 | "number" : 0 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/annotated-resource-resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "pojos" : [ { 4 | "text" : "test1", 5 | "number" : 1, 6 | "_links" : { 7 | "self" : { 8 | "href" : "localhost" 9 | } 10 | } 11 | } ] 12 | }, 13 | "_links" : { 14 | "self" : { 15 | "href" : "localhost" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/curied-document.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "foo" 5 | }, 6 | "foo:myrel" : { 7 | "href" : "bar" 8 | }, 9 | "curies" : [ { 10 | "href" : "http://localhost:8080/rels/{rel}", 11 | "name" : "foo", 12 | "templated" : true 13 | } ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/employee-resource-support.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Frodo Baggins", 3 | "_links" : { 4 | "self" : { 5 | "href" : "/employees/1" 6 | } 7 | }, 8 | "_templates" : { 9 | "foo" : { 10 | "method" : "POST", 11 | "properties" : [ { 12 | "name" : "name", 13 | "type" : "text" 14 | } ] 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/empty-document.json: -------------------------------------------------------------------------------- 1 | { } 2 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/empty-embedded-pojos.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "pojos" : [ ] 4 | } 5 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/hal-forms-custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Frodo Baggins", 3 | "role" : "ring bearer", 4 | "_links" : { 5 | "self" : { 6 | "href" : "http://localhost/employees/0" 7 | }, 8 | "employees" : { 9 | "href" : "http://localhost/employees" 10 | } 11 | }, 12 | "_templates" : { 13 | "updateEmployee" : { 14 | "method" : "PUT", 15 | "properties" : [ { 16 | "name" : "name", 17 | "required" : true, 18 | "type" : "text" 19 | }, { 20 | "name" : "role", 21 | "type" : "text" 22 | } ] 23 | }, 24 | "partiallyUpdateEmployee" : { 25 | "method" : "PATCH", 26 | "properties" : [ { 27 | "name" : "name", 28 | "type" : "text" 29 | }, { 30 | "name" : "role", 31 | "type" : "text" 32 | } ] 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/hal-forms-link-discoverer.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "self": { 4 | "href": "selfHref" 5 | }, 6 | "relation": [ 7 | { 8 | "href": "firstHref" 9 | }, 10 | { 11 | "href": "secondHref" 12 | } 13 | ], 14 | "http://www.foo.com/bar": { 15 | "href": "fullRelHref" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/hal-forms-link.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "/customer/1", 5 | "hreflang" : "en", 6 | "media" : "pdf", 7 | "title" : "pdf customer copy", 8 | "type" : "portable document", 9 | "deprecation" : "https://example.com/customers/deprecated", 10 | "profile" : "my-profile", 11 | "name" : "my-name" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/link-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "search" : { 4 | "href" : "/foo{?bar}", 5 | "templated" : true 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/link-with-title.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "ns:foobar" : { 4 | "href" : "target", 5 | "title" : "Foobar's title!" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/list-link-reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : [ { 4 | "href" : "localhost" 5 | }, { 6 | "href" : "localhost2" 7 | } ] 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/multiple-curies-document.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "default:myrel" : { 4 | "href" : "foo" 5 | }, 6 | "curies" : [ { 7 | "href" : "bar", 8 | "name" : "foo" 9 | }, { 10 | "href" : "foo", 11 | "name" : "bar" 12 | } ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/multiple-resource-resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "content" : [ { 4 | "text" : "test1", 5 | "number" : 1, 6 | "_links" : { 7 | "self" : { 8 | "href" : "localhost" 9 | } 10 | } 11 | }, { 12 | "text" : "test2", 13 | "number" : 2, 14 | "_links" : { 15 | "self" : { 16 | "href" : "localhost" 17 | } 18 | } 19 | } ] 20 | }, 21 | "_links" : { 22 | "self" : { 23 | "href" : "localhost" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/new-employee.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Samwise Gamgee", 3 | "role" : "gardener", 4 | "_links" : { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "collection" : { 4 | "href" : "/employees" 5 | }, 6 | "self" : { 7 | "href" : "/employees/1" 8 | } 9 | }, 10 | "_templates" : { 11 | "default" : { 12 | "title" : "HAL-FORMS unit test", 13 | "method" : "get", 14 | "contentType" : "application/hal+json", 15 | "properties" : [ { 16 | "name" : "my-name", 17 | "readOnly" : true, 18 | "value" : "my-value", 19 | "prompt" : "my-prompt", 20 | "regex" : "my-regex", 21 | "required" : true 22 | } ] 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/simple-embedded-resource-reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "content" : [ "first", "second" ] 4 | }, 5 | "_links" : { 6 | "self" : { 7 | "href" : "localhost" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/simple-resource-unwrapped.json: -------------------------------------------------------------------------------- 1 | { 2 | "text" : "test1", 3 | "number" : 1, 4 | "_links" : { 5 | "self" : { 6 | "href" : "localhost" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/single-embedded-resource-reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "content" : [ { 4 | "text" : "test1", 5 | "number" : 1, 6 | "_links" : { 7 | "self" : { 8 | "href" : "localhost" 9 | } 10 | } 11 | } ] 12 | }, 13 | "_links" : { 14 | "self" : { 15 | "href" : "localhost" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/single-link-reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "localhost" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/forms/single-non-curie-document.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "foo" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-custom.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Frodo Baggins", 3 | "role" : "ring bearer", 4 | "_links" : { 5 | "self" : { 6 | "href" : "http://localhost/employees/0" 7 | }, 8 | "employees" : { 9 | "href" : "http://localhost/employees" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-embedded-author-illustrator.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "author" : { 4 | "name" : "Alan Watts", 5 | "born" : "January 6, 1915", 6 | "died" : "November 16, 1973", 7 | "_links" : { 8 | "self" : { 9 | "href" : "/people/alan-watts" 10 | } 11 | } 12 | }, 13 | "illustrator" : { 14 | "name" : "John Smith", 15 | "_links" : { 16 | "self" : { 17 | "href" : "/people/john-smith" 18 | } 19 | } 20 | } 21 | }, 22 | "_links" : { 23 | "self" : { 24 | "href" : "/books/the-way-of-zen" 25 | }, 26 | "author" : { 27 | "href" : "/people/alan-watts" 28 | }, 29 | "illustrator" : { 30 | "href" : "/people/john-smith" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-embedded-collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "authors" : [ { 4 | "name" : "Greg L. Turnquist", 5 | "_links" : { 6 | "self" : { 7 | "href" : "http://localhost/author/1" 8 | }, 9 | "authors" : { 10 | "href" : "http://localhost/authors" 11 | } 12 | } 13 | }, { 14 | "name" : "Craig Walls", 15 | "_links" : { 16 | "self" : { 17 | "href" : "http://localhost/author/2" 18 | }, 19 | "authors" : { 20 | "href" : "http://localhost/authors" 21 | } 22 | } 23 | }, { 24 | "name" : "Oliver Drotbohm", 25 | "_links" : { 26 | "self" : { 27 | "href" : "http://localhost/author/3" 28 | }, 29 | "authors" : { 30 | "href" : "http://localhost/authors" 31 | } 32 | } 33 | } ] 34 | }, 35 | "_links" : { 36 | "self" : { 37 | "href" : "http://localhost/authors" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-empty.json: -------------------------------------------------------------------------------- 1 | { } 2 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-explicit-and-implicit-relations.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "staffs" : [ { 4 | "name" : "Frodo Baggins", 5 | "role" : "ring bearer" 6 | }, { 7 | "name" : "Bilbo Baggins", 8 | "role" : "burglar" 9 | } ], 10 | "products" : [ { 11 | "name" : "ring of power", 12 | "price" : 999.99 13 | }, { 14 | "name" : "Saruman's staff", 15 | "price" : 9.99 16 | } ], 17 | "ring bearers" : { 18 | "name" : "Frodo Baggins", 19 | "role" : "ring bearer" 20 | }, 21 | "burglars" : { 22 | "name" : "Bilbo Baggins", 23 | "role" : "burglar" 24 | } 25 | }, 26 | "_links" : { 27 | "self" : { 28 | "href" : "/people/alan-watts" 29 | }, 30 | "frodo" : { 31 | "href" : "/people/frodo-baggins" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-link-discoverer.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links": { 3 | "self": { 4 | "href": "selfHref" 5 | }, 6 | "relation": [ 7 | { 8 | "href": "firstHref" 9 | }, 10 | { 11 | "href": "secondHref" 12 | } 13 | ], 14 | "http://www.foo.com/bar": { 15 | "href": "fullRelHref" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-link.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "/customer/1", 5 | "hreflang" : "en", 6 | "media" : "pdf", 7 | "title" : "pdf customer copy", 8 | "type" : "portable document", 9 | "deprecation" : "https://example.com/customers/deprecated", 10 | "profile" : "my-profile", 11 | "name" : "my-name" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-multiple-types.json: -------------------------------------------------------------------------------- 1 | { 2 | "_embedded" : { 3 | "staffs" : [ { 4 | "name" : "Frodo Baggins", 5 | "role" : "ring bearer" 6 | }, { 7 | "name" : "Bilbo Baggins", 8 | "role" : "burglar" 9 | } ], 10 | "products" : [ { 11 | "name" : "ring of power", 12 | "price" : 999.99 13 | }, { 14 | "name" : "Saruman's staff", 15 | "price" : 9.99 16 | } ] 17 | }, 18 | "_links" : { 19 | "self" : { 20 | "href" : "/people/alan-watts" 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-one-thing.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Greg L. Turnquist", 3 | "_links" : { 4 | "self" : { 5 | "href" : "http://localhost/author/1" 6 | }, 7 | "authors" : { 8 | "href" : "http://localhost/authors" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-single-item.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Alan Watts", 3 | "born" : "January 6, 1915", 4 | "died" : "November 16, 1973", 5 | "_links" : { 6 | "self" : { 7 | "href" : "/people/alan-watts" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/hal/hal-two-things.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Greg L. Turnquist", 3 | "_links" : { 4 | "self" : { 5 | "href" : "http://localhost/author/1" 6 | }, 7 | "authors" : { 8 | "href" : "http://localhost/authors" 9 | } 10 | }, 11 | "_embedded" : { 12 | "product" : { 13 | "name" : "Alf alarm clock", 14 | "price" : 19.99 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/detail-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "detail" : "test detail" 3 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "https://example.com/probs/out-of-credit", 3 | "title" : "You do not have enough credit.", 4 | "detail" : "Your current balance is 30, but that costs 50.", 5 | "instance" : "/account/12345/msgs/abc", 6 | "balance" : 30, 7 | "accounts" : [ "/account/12345", "/account/67890" ], 8 | "status" : 400 9 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/http-status-problem.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "about:blank", 3 | "title" : "Not Found", 4 | "status" : 404 5 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/instance-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "instance" : "http://example.com/employees/1471" 3 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/reference-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "https://example.com/probs/out-of-credit", 3 | "title": "You do not have enough credit.", 4 | "detail": "Your current balance is 30, but that costs 50.", 5 | "instance": "/account/12345/msgs/abc", 6 | "balance": 30, 7 | "accounts": ["/account/12345", 8 | "/account/67890"] 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/reference-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "https://example.net/validation-error", 3 | "title": "Your request parameters didn't validate.", 4 | "invalid-params": [ { 5 | "name": "age", 6 | "reason": "must be a positive integer" 7 | }, 8 | { 9 | "name": "color", 10 | "reason": "must be 'green', 'red' or 'blue'"} 11 | ] 12 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/status-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "status" : 502 3 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/title-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "title" : "test title" 3 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/problem/type-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "http://example.com/problem-details" 3 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/create-employee.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber": { 3 | "version": "1.0", 4 | "data": [ 5 | { 6 | "name": "employee", 7 | "data": [ 8 | { 9 | "name": "role", 10 | "value": "gardener" 11 | }, 12 | { 13 | "name": "name", 14 | "value": "Samwise Gamgee" 15 | } 16 | ] 17 | } 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/link-discovery.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : 3 | { 4 | "version" : "1.0", 5 | "data" : 6 | [ 7 | { 8 | "rel" : ["self"], 9 | "url" : "selfHref" 10 | }, 11 | { 12 | "rel" : ["relation"], 13 | "url" : "firstHref" 14 | }, 15 | { 16 | "rel" : ["relation"], 17 | "url" : "secondHref" 18 | }, 19 | { 20 | "rel" : ["http://www.foo.com/bar"], 21 | "url" : "fullRelHref" 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/paged-resources-empty-page.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "next" ], 9 | "url" : "foo" 10 | }, { 11 | "rel" : [ "prev" ], 12 | "url" : "bar" 13 | }, { 14 | "data" : [ { 15 | "rel" : [ "self" ], 16 | "url" : "/employees/1" 17 | }, { 18 | "name" : "employee", 19 | "data" : [ { 20 | "name" : "role", 21 | "value" : "ring bearer" 22 | }, { 23 | "name" : "name", 24 | "value" : "Frodo" 25 | } ] 26 | } ] 27 | }, { 28 | "name" : "page", 29 | "data" : [] 30 | } ] 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/paged-resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "next" ], 9 | "url" : "foo" 10 | }, { 11 | "rel" : [ "prev" ], 12 | "url" : "bar" 13 | }, { 14 | "data" : [ { 15 | "rel" : [ "self" ], 16 | "url" : "/employees/1" 17 | }, { 18 | "name" : "employee", 19 | "data" : [ { 20 | "name" : "role", 21 | "value" : "ring bearer" 22 | }, { 23 | "name" : "name", 24 | "value" : "Frodo" 25 | } ] 26 | } ] 27 | }, { 28 | "name" : "page", 29 | "data" : [ { 30 | "name" : "number", 31 | "value" : 0 32 | }, { 33 | "name" : "size", 34 | "value" : 2 35 | }, { 36 | "name" : "totalElements", 37 | "value" : 4 38 | }, { 39 | "name" : "totalPages", 40 | "value" : 2 41 | } ] 42 | } ] 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/reference-links-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "collection" : { 4 | "href" : "/employees" 5 | }, 6 | "self" : { 7 | "href" : "/employees/1" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-support-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "orders" ], 9 | "url" : "localhost2" 10 | } ] 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-support-pojo-empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "/employees/1" 7 | }, { 8 | "rel" : [ "employees" ], 9 | "url" : "/employees" 10 | }, { 11 | "name" : "employeeResource", 12 | "data" : [] } ] 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-support-pojo.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "/employees/1" 7 | }, { 8 | "rel" : [ "employees" ], 9 | "url" : "/employees" 10 | }, { 11 | "name" : "employeeResource", 12 | "data" : [ { 13 | "name" : "role", 14 | "value" : "ring bearer" 15 | }, { 16 | "name" : "name", 17 | "value" : "Frodo" 18 | } ] 19 | } ] 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-support.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | } ] 8 | } 9 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-with-empty-pojo.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "/employees/1" 7 | }, { 8 | "name" : "employee", 9 | "data" : [ ] 10 | } ] 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-with-simple-pojo.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "/employees/1" 7 | }, { 8 | "name" : "employee", 9 | "data" : [ { 10 | "name" : "role", 11 | "value" : "ring bearer" 12 | }, { 13 | "name" : "name", 14 | "value" : "Frodo" 15 | } ] 16 | } ] 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource-with-templated-link.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "order" ], 6 | "url" : "/orders{?id}", 7 | "templated" : true 8 | } ] 9 | } 10 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "name" : "string", 9 | "data" : [ { 10 | "value" : "first" 11 | } ] 12 | } ] 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource2.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "custom" ], 6 | "url" : "localhost" 7 | }, { 8 | "name" : "string", 9 | "data" : [ { 10 | "value" : "second" 11 | } ] 12 | } ] 13 | } 14 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource3.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "second" ], 9 | "url" : "second" 10 | }, { 11 | "rel" : [ "third" ], 12 | "url" : "third" 13 | }, { 14 | "name" : "string", 15 | "data" : [ { 16 | "value" : "third" 17 | } ] 18 | } ] 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resource4.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self", "https://example.org/rels/todo" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "second" ], 9 | "url" : "second" 10 | }, { 11 | "rel" : [ "third" ], 12 | "url" : "third" 13 | }, { 14 | "name" : "string", 15 | "data" : [ { 16 | "value" : "third" 17 | } ] 18 | } ] 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resources-with-empty-resource-objects.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "next" ], 9 | "url" : "/page/2" 10 | }, { 11 | "data" : [ { 12 | "rel" : [ "self" ], 13 | "url" : "localhost" 14 | }, { 15 | "rel" : [ "orders" ], 16 | "url" : "orders" 17 | }, { 18 | "name" : "string", 19 | "data" : [ { 20 | "value" : "first" 21 | } ] 22 | } ] 23 | }, { 24 | "data" : [] } ] 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resources-with-resource-objects-and-empty-value.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "next" ], 9 | "url" : "/page/2" 10 | }, { 11 | "data" : [ { 12 | "rel" : [ "self" ], 13 | "url" : "localhost" 14 | }, { 15 | "rel" : [ "orders" ], 16 | "url" : "orders" 17 | }, { 18 | "name" : "string", 19 | "data" : [] 20 | } ] 21 | }, { 22 | "data" : [ { 23 | "rel" : [ "self" ], 24 | "url" : "remotehost" 25 | }, { 26 | "rel" : [ "orders" ], 27 | "url" : "order" 28 | }, { 29 | "name" : "string", 30 | "data" : [ { 31 | "value" : "second" 32 | } ] 33 | } ] 34 | } ] 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resources-with-resource-objects.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "rel" : [ "next" ], 9 | "url" : "/page/2" 10 | }, { 11 | "data" : [ { 12 | "rel" : [ "self" ], 13 | "url" : "localhost" 14 | }, { 15 | "rel" : [ "orders" ], 16 | "url" : "orders" 17 | }, { 18 | "name" : "string", 19 | "data" : [ { 20 | "value" : "first" 21 | } ] 22 | } ] 23 | }, { 24 | "data" : [ { 25 | "rel" : [ "self" ], 26 | "url" : "remotehost" 27 | }, { 28 | "rel" : [ "orders" ], 29 | "url" : "order" 30 | }, { 31 | "name" : "string", 32 | "data" : [ { 33 | "value" : "second" 34 | } ] 35 | } ] 36 | } ] 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/uber/resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "uber" : { 3 | "version" : "1.0", 4 | "data" : [ { 5 | "rel" : [ "self" ], 6 | "url" : "localhost" 7 | }, { 8 | "data" : [ { 9 | "name" : "string", 10 | "data" : [ { 11 | "value" : "first" 12 | } ] 13 | } ] 14 | }, { 15 | "data" : [ { 16 | "name" : "string", 17 | "data" : [ { 18 | "value" : "second" 19 | } ] 20 | } ] 21 | } ] 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/vnderror/vnderror-multiple-items.json: -------------------------------------------------------------------------------- 1 | { 2 | "total": 2, 3 | "_embedded": { 4 | "errors": [ 5 | { 6 | "message": "\"username\" field validation failed", 7 | "logref": 50, 8 | "_links": { 9 | "help": { 10 | "href": "http://.../" 11 | } 12 | } 13 | }, 14 | { 15 | "message": "\"postcode\" field validation failed", 16 | "logref": 55, 17 | "_links": { 18 | "help": { 19 | "href": "http://.../" 20 | } 21 | } 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/vnderror/vnderror-nested.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Validation failed", 3 | "logref": 42, 4 | "_links": { 5 | "describes": { 6 | "href": "http://path.to/describes" 7 | }, 8 | "help": { 9 | "href": "http://path.to/help" 10 | }, 11 | "about": { 12 | "href": "http://path.to/user/resource/1" 13 | } 14 | }, 15 | "_embedded": { 16 | "errors": [ 17 | { 18 | "message": "Username must contain at least three characters", 19 | "path": "/username", 20 | "_links": { 21 | "about": { 22 | "href": "http://path.to/user/resource/1" 23 | } 24 | } 25 | } 26 | ] 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/vnderror/vnderror-single-item.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Validation failed", 3 | "path": "/username", 4 | "logref": 42, 5 | "_links": { 6 | "about": { 7 | "href": "http://path.to/user/resource/1" 8 | }, 9 | "describes": { 10 | "href": "http://path.to/describes" 11 | }, 12 | "help": { 13 | "href": "http://path.to/help" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/resources/org/springframework/hateoas/mediatype/vnderror/vnderror-string-logref.json: -------------------------------------------------------------------------------- 1 | { 2 | "message" : "message", 3 | "path" : "path", 4 | "logref" : "alphaLogref", 5 | "_links" : { 6 | "bar" : { 7 | "href" : "foo" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/pagedresources.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/springagram-item-without-image.json: -------------------------------------------------------------------------------- 1 | { 2 | "description" : "cat", 3 | "_links" : { 4 | "self" : { 5 | "href" : "%s/springagram/items/1{?projection}", 6 | "templated" : true 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/resources/springagram-item.json: -------------------------------------------------------------------------------- 1 | { 2 | "image" : "%s/springagram/file/cat", 3 | "description" : "cat", 4 | "_links" : { 5 | "self" : { 6 | "href" : "%s/springagram/items/1{?projection}", 7 | "templated" : true 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/springagram-items.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "self" : { 4 | "href" : "%s/springagram/items{?projection}", 5 | "templated" : true 6 | } 7 | }, 8 | "_embedded" : { 9 | "items" : [ { 10 | "description" : "cat", 11 | "_links" : { 12 | "self" : { 13 | "href" : "%s/springagram/items/1{?projection}", 14 | "templated" : true 15 | } 16 | } 17 | }, { 18 | "description" : "caterpillar", 19 | "_links" : { 20 | "self" : { 21 | "href" : "%s/springagram/items/2{?projection}", 22 | "templated" : true 23 | } 24 | } 25 | } ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/resources/springagram-root.json: -------------------------------------------------------------------------------- 1 | { 2 | "_links" : { 3 | "items" : { 4 | "href" : "%s/springagram/items{?projection}", 5 | "templated" : true 6 | }, 7 | "profile" : { 8 | "href" : "%s/springagram/alps" 9 | } 10 | } 11 | } 12 | --------------------------------------------------------------------------------